第五章 串口试验 前面几章介绍了 W7500 的 IO 口操作。本章教大家如何使用W7500的串口来发送和接收数据。 本章将实现如下功能:W7500通过串口和上位机的对话,W7500在收到上位机发过来的字符串后,原原本本的返回给上位机。
本章分为如下几个小节:
5.1 W7500 串口简介
5.2 硬件设计
5.3 软件设计
5.4 下载验证
5.1 W7500 串口简介串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的MCU 都会带有串口,W7500自然也不例外。W7500 的串口资源相当丰富的,功能也相当强劲。W7500EVB开发板所使用的W7500 最多可提供 3 路USART,有分数波特率发生器、支持同步单线通信和半双工单线通讯。 接下来将主要从库函数操作层面结合寄存器的描述,告诉用户如何设置串口,以达到最基本的通信功能。本章,将实现利用串口2接收从PC发送过来的数据,再把接收到的数据直接发送回给PC。 串口设置的步骤可以总结为如下几:
1 串口参数初始化
2 开启中断并且初始化 NVIC(如果需要开启中断才需要以下这个步骤)
3 使能串口中断
4 编写中断处理函数
|
下面就简单介绍下这几个与串口基本配置直接相关的几个固件库函数。 这些函数和定义主要分布在W7500x_uart.h 和W7500x_uart.c文件中。 这里要注意的是串口初始化函数有两个,一个是专门初始化串口2的,另一个是用来初始化串口1和串口0的。 先来看看初始化串口1和串口0的函数: - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">uint32_t UART_Init(UART_TypeDef *UARTx,
- UART_InitTypeDef* UART_InitStruct)</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码UART_Init函数有两个参数, 第一个参数是用来指定UART,取值范围为UART0~UART1。第二个参数为初始化参数结构体指针,结构体类型为UART_InitTypeDef,下面我们看看这个结构体的定义。 - <span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:#0070C0">typedef struct</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- {
- uint32_t UART_BaudRate;
- uint16_t UART_WordLength;
- uint16_t UART_StopBits;
- uint16_t UART_Parity;
- uint16_t UART_Mode;
- uint16_t
- UART_HardwareFlowControl;
- } UART_InitTypeDef;</span>
复制代码
|
下面通过一个UART0 初始化实例来讲解这个结构体的成员变量的含义。 - UART_InitTypeDef UART_InitStructure;
- UART_InitStructure.UART_BaudRate = 115200;
- UART_InitStructure.UART_WordLength = UART_WordLength_8b;
- UART_InitStructure.UART_StopBits = UART_StopBits_1;
- UART_InitStructure.UART_Parity = UART_Parity_No;
- UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;
- UART_InitStructure.UART_HardwareFlowControl =
- UART_HardwareFlowControl_None;
- UART_Init(UART0,&UART_InitStructure);
复制代码
|
上面代码的意思是初始化串口0,从上面初始化代码可以看出,结构体UART_InitTypeDef 的第一个成员变量UART_BaudRate用来设置串口的波特率, 第二个成员变量UART_WordLength是用来设置数据bit的, 第三个成员变量UART_StopBits是设置停止位, 第四个成员变量UART_Parity是设置校验位, 第五个成员变量UART_Mode这是使能串口的工作模式, 第六个成员变量UART_HardwareFlowControl设置串口的硬件控制流。 串口2初始化是通过S_USART_Init()函数实现的: - <span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">uint32_t S_UART_Init(uint32_t baud)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span>
复制代码
|
S_UART_Init函数是使能UART2,波特率为传参值。 W7500的发送与接收是通过数据寄存器USART_DR 来实现的,这是一个双寄存器,包含了TDR 和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存到该寄存器内。 W7500库函数操作 USART_DR 寄存器发送数据是UART_SendData和S_UART_SendData函数。 - <span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:#0070C0">void</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black"> UART_SendData(UART_TypeDef*
- UARTx, uint16_t Data)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:="" tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black">
- </span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;
- color:#0070C0">void</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black"> S_UART_SendData(uint16_t Data)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span>
复制代码
|
可以通过调用这两个函数来发送数据。 W7500库函数操作 USART_DR 寄存器读取串口接收到的数据可以调用UART_ReceiveData函数和S_ UART_ReceiveData函数。 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">uint16_t UART_ReceiveData(UART_TypeDef* UARTx)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- uint16_t S_UART_ReceiveData()</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码
通过该函数可以读取串口接受到的数据。 串口的状态可以通过状态寄存器USART_FR 读取,在固件库函数里面,读取串口状态的是UART_GetFlagStatus函数和S_ UART_GetFlagStatus函数。 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx,
- uint16_t UART_FLAG)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:="" tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black">
- FlagStatus S_UART_GetFlagStatus(uint16_t UART_FLAG)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码UART_GetFlagStatus函数和S_UART_GetFlagStatus函数的参数非常关键, 它是标示我们要查看串口的哪种状态。比如要读取判断RXF寄存器看它是否正在发送数据,可以通过UART_GetFlagStatus函数或S_UART_GetFlagStatus函数来读取。 - <span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">UART_GetFlagStatus(UART_FLAG_RXFE)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- S_UART_GetFlagStatus(S_UART_FLAG_RXF)</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span>
复制代码
|
[/table]
这些标识号在W7500x_uart.h里面是通过宏定义定义的: - <p class="MsoNormal"><span lang="EN-US" style="font-size:9.0pt">#define
- UART_FLAG_RI ((uint16_t)0x01UL << 8) /* Ring
- indicator */
- #define UART_FLAG_TXFE ((uint16_t)0x01UL
- << 7) /* Transmit FIFO empty */
- #define UART_FLAG_RXFF ((uint16_t)0x01UL
- << 6) /* Receive FIFO full */
- #define UART_FLAG_TXFF ((uint16_t)0x01UL
- << 5) /* Transmit FIFO full */
- #define UART_FLAG_RXFE ((uint16_t)0x01UL
- << 4) /* Receive FIFO empty */
- #define UART_FLAG_BUSY ((uint16_t)0x01UL
- << 3) /* UART busy */
- #define UART_FLAG_DCD ((uint16_t)0x01UL
- << 2) /* Data carrier detect */
- #define UART_FLAG_DSR ((uint16_t)0x01UL
- << 1) /* Data set ready */
- #define UART_FLAG_CTS ((uint16_t)0x01UL
- << 0) /* Clear to send */
- #define S_UART_FLAG_RXO ((uint16_t)0x01UL << 3) /* RX buffer
- Overrun */
- #define S_UART_FLAG_TXO ((uint16_t)0x01UL << 2) /* TX buffer
- Overrun */
- #define S_UART_FLAG_RXF ((uint16_t)0x01UL << 1) /* RX
- buffer Full */<o:p></o:p></span></p>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:9.0pt">#define
- S_UART_FLAG_TXF
- ((uint16_t)0x01UL << 0) /*!< TX buffer Full */</span></p>
复制代码
|
|
| 当需要使能串口中断时,可以调用UART_ITConfig函数和S_ UART_ITConfig函数。 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:#0070C0">void</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black"> UART_ITConfig(UART_TypeDef*
- UARTx, uint16_t UART_IT, FunctionalState NewState)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- </span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;
- color:#0070C0">void</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black"> S_UART_ITConfig(uint16_t
- S_UART_IT, FunctionalState NewState)</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码UART_ITConfig函数的第一个参数是表示使能那个串口,第二个参数是使能哪种中断。比如在接收到数据的时候,发生中断。 - <span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">UART_ITConfig(UART0, UART_IT_FLAG_RXI, ENABLE)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- S_UART_ITConfig(UART_IT_FLAG_RXI, ENABLE)</span><span style="font-size:
- 10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;="" mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span>
复制代码
| |
|
|
| 当使能了某个中断后,该中断发生时,状态寄存器中的对应标志位会改变。在中断处理函数中,可以调用UART_GetITStatus函数或S_UART_GetITStatus函数来读取判断。 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">ITStatus UART_GetITStatus(UART_TypeDef* UARTx, uint16_t
- UART_IT)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:="" tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;
- mso-bidi-font-family:Tahoma;color:black">
- ITStatus S_UART_GetITStatus(uint16_t S_UART_IT)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码 | 通过 UART_GetITStatus函数来判断串口接收数据完成的方法是。 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">UART_GetITStatus(UART0, UART_IT_FLAG_RXI)</span><span style="font-size:10.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">
- S_UART_GetITStatus(S_UART_IT_FLAG_RXI)</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">;</span></p></div></td></tr></tbody></table>
复制代码 | 返回值是1,说明是串口接收中断发生。
| 5.2 硬件设计 本实验需要用到的硬件资源有: 1) UART2 2) PC 电路在W7500EVB 开发板上默认是已经连接好了的。所以在硬件上不需要动任何东西。 5.3 软件设计在W7500EVB UART工程里,可以看到 main.c 里面编写有如下代码: - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt"><span lang="EN-US" style="font-size:9.0pt">int main()
- {
- uint8_t i = 0,tx_dara[100] = "</span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma"="">炜世科技</span><span lang="EN-US" style="font-size:9.0pt">W7500EVB\r\n\t</span><span style="font-size:9.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma"="">串口试验</span><span lang="EN-US" style="font-size:9.0pt">\r\n";
-
- SystemInit(); /*
- </span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma"="">系统内部时钟初始化</span><span lang="EN-US" style="font-size:9.0pt"> */
- delay_init(); /* </span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma"="">系统滴答时钟配置</span><span lang="EN-US" style="font-size:9.0pt">*/
- S_UART_Init(115200); /* </span><span style="font-size:9.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma"="">初始化串口通信</span><span lang="EN-US" style="font-size:9.0pt">:115200@8-n-2*/
- S_UART_ITConfig(S_UART_IT_FLAG_RXI,
- ENABLE);
- NVIC_ClearPendingIRQ(UART2_IRQn);
- NVIC_EnableIRQ(UART2_IRQn);
-
- /*-----------------------------------------------------------------------------------------
- |
- </span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma"="">炜世科技—</span><span lang="EN-US" style="font-size:9.0pt">WIZnet W7500</span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma"="">官方代理商,全程技术支持,价格绝对优势!</span><span style="font-size:9.0pt"> <span lang="EN-US">|
-
- ------------------------------------------------------------------------------------------*/
-
- while(tx_dara[i] != '\0')
- {
- S_UART_SendData(tx_dara[i]); //</span></span><span style="font-size:
- 9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;="" mso-hansi-font-family:tahoma"="">通过</span><span lang="EN-US" style="font-size:
- 9.0pt">UART2</span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;="" mso-ascii-font-family:tahoma;mso-hansi-font-family:tahoma"="">发送</span><span lang="EN-US" style="font-size:9.0pt">
- while(S_UART_GetFlagStatus(S_UART_FLAG_TXF)); //</span><span style="font-size:9.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma"="">判读</span><span lang="EN-US" style="font-size:9.0pt">UART1</span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma"="">忙</span><span lang="EN-US" style="font-size:9.0pt">
- i++;
- }
-
- while(1)
- {
- ;
- }
- }</span></p></div></td></tr></tbody></table>
复制代码在 W7500x_it.c 里面编写如下代码:
- <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:9.0pt">void
- UART2_Handler(void)
- {
- uint8_t ReadValue;
-
- ReadValue = S_UART_ReceiveData();
- S_UART_SendData(ReadValue); //</span><span style="font-size:9.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma"="">通过</span><span lang="EN-US" style="font-size:9.0pt">UART2</span><span style="font-size:9.0pt;font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:="" tahoma;mso-hansi-font-family:tahoma"="">发送</span><span lang="EN-US" style="font-size:9.0pt">
- S_UART_ClearITPendingBit(S_UART_IT_FLAG_RXI);
-
- }</span></p></div></td></tr></tbody></table>
复制代码 | 这里开启了UART2的接收中断无论main.c在执行什么操作只要PC向W7500EVB的UART2发送数据就会进入中断服务函数,这个中断会接收PC发送过来的数据,然后在发送回PC。 这里已经对printf的底层函数修改过了所以可以通过printf函数来输出串口数据了 - <table cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
- <td>
- <div>
- <p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:
- Tahoma;color:black">printf(“</span><span style="font-size:10.0pt;
- font-family:" 微软雅黑",sans-serif;mso-ascii-font-family:tahoma;mso-hansi-font-family:="" tahoma;mso-bidi-font-family:tahoma;color:black"="">串口试验</span><span lang="EN-US" style="font-size:10.0pt;mso-bidi-font-family:Tahoma;color:black">\r\n”);</span></p></div></td></tr></tbody></table>
复制代码 |
|
| 如果需要更改printf输出的串口可以通过修改USING_UART2这个宏定义来完成。 - #include <stdio.h>
- #include "W7500x.h"
-
- #define USING_UART2 // USING_UART0/
- USING_UART1
-
- #if defined (USING_UART0)
- #define UART_SEND_BYTE(ch) UartPutc(UART0,ch)
- #define UART_RECV_BYTE() UartGetc(UART0)
- #elif defined (USING_UART1)
- #define UART_SEND_BYTE(ch) UartPutc(UART1,ch)
- #define UART_RECV_BYTE() UartGetc(UART1)
- #elif defined (USING_UART2)
- #define UART_SEND_BYTE(ch) S_UartPutc(ch)
- #define UART_RECV_BYTE() S_UartGetc()
- #endif
-
- #if defined ( __CC_ARM )
- /******************************************************************************/
- /* Retarget functions for ARM DS-5 Professional / Keil MDK */
- /******************************************************************************/
- #include <time.h>
- #include <rt_misc.h>
- #pragma import(__use_no_semihosting_swi)
- struct __FILE { int handle; /* Add whatever you need here */ };
- FILE __stdout;
- FILE __stdin;
复制代码
| |
|
| 5.4 下载验证 把程序下载到W7500EVB板子,接着打开串口调试工具,设置串口为开发板的USB 转串口(CH340C虚拟串口,得根据自己的电脑选择,我的电脑是COM11,另外,请注意:波特率是115200),如图5.4.1所示: 图5.4.1 W7500EVB串口试验结果1 可以看出, W7500 的串口数据发送和接受是没问题的,如图5.4.2所示: 图5.4.2 W7500EVB串口试验结果2
|
|
|
|
|
| [table=98%] |
|