查看:
2073
|
回复:
1
|
M0+MAC+TCP/IP 以太网单芯片方案 W7500EVB用户手册连载(4)--实战篇
|
WSGustin
29
主题
48
回复 |
发表于2018-02-28 18:47:27
|
显示全部楼层
1#
电梯直达
W7500(W7500P)芯片简介: |
WSGustin
29
主题
48
回复 |
发表于2018-02-28 18:54:16
|
显示全部楼层
2#
第五章 串口试验前面几章介绍了 W7500 的 IO 口操作。本章教大家如何使用W7500 的串口来发送和接收数据。 本章将实现如下功能:W7500通过串口和上位机的对话,W7500在收到上位机发过来的字符串后,原原本本的返回给上位机。 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的函数: uint32_t UART_Init(UART_TypeDef *UARTx, UART_InitTypeDef* UART_InitStruct); UART_Init函数有两个参数, 第一个参数是用来指定 UART,取值范围为UART0~UART1。第二个参数为初始化参数结构体指针,结构体类型为UART_InitTypeDef,下面我们看看这个结构体的定义。 typedef struct { 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; 下面通过一个 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()函数实现的: uint32_t S_UART_Init(uint32_t baud); S_UART_Init函数是使能UART2,波特率为传参值。 W7500 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存到该寄存器内。 W7500 库函数操作 USART_DR 寄存器发送数据是UART_SendData和S_UART_SendData函数。 void UART_SendData(UART_TypeDef* UARTx, uint16_t Data); void S_UART_SendData(uint16_t Data); 可以通过调用这两个函数来发送数据。 W7500库函数操作 USART_DR 寄存器读取串口接收到的数据可以调用UART_ReceiveData函数和S_ UART_ReceiveData函数。 uint16_t UART_ReceiveData(UART_TypeDef* UARTx); uint16_t S_UART_ReceiveData(); 通过该函数可以读取串口接受到的数据。 串口的状态可以通过状态寄存器 USART_FR 读取,在固件库函数里面,读取串口状态的是UART_GetFlagStatus函数和S_ UART_GetFlagStatus函数。 FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx, uint16_t UART_FLAG); FlagStatus S_UART_GetFlagStatus(uint16_t UART_FLAG); UART_GetFlagStatus函数和S_UART_GetFlagStatus函数的参数非常关键, 它是标示我们要查看串口的哪种状态。比如要读取判断RXF寄存器看它是否正在发送数据,可以通过UART_GetFlagStatus函数或S_UART_GetFlagStatus函数来读取。 UART_GetFlagStatus(UART_FLAG_RXFE); S_UART_GetFlagStatus(S_UART_FLAG_RXF); 这些标识号在W7500x_uart.h里面是通过宏定义定义的: #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 */ #define S_UART_FLAG_TXF ((uint16_t)0x01UL << 0) /*!< TX buffer Full */ 当需要使能串口中断时,可以调用UART_ITConfig函数和S_ UART_ITConfig函数。 void UART_ITConfig(UART_TypeDef* UARTx, uint16_t UART_IT, FunctionalState NewState); void S_UART_ITConfig(uint16_t S_UART_IT, FunctionalState NewState); UART_ITConfig函数的第一个参数是表示使能那个串口,第二个参数是使能哪种中断。比如在接收到数据的时候,发生中断。 UART_ITConfig(UART0, UART_IT_FLAG_RXI, ENABLE); S_UART_ITConfig(UART_IT_FLAG_RXI, ENABLE); 当使能了某个中断后,该中断发生时,状态寄存器中的对应标志位会改变。在中断处理函数中,可以调用UART_GetITStatus函数或S_UART_GetITStatus函数来读取判断。 ITStatus UART_GetITStatus(UART_TypeDef* UARTx, uint16_t UART_IT); ITStatus S_UART_GetITStatus(uint16_t S_UART_IT); 通过 UART_GetITStatus函数来判断串口接收数据完成的方法是。 UART_GetITStatus(UART0, UART_IT_FLAG_RXI); S_UART_GetITStatus(S_UART_IT_FLAG_RXI); 返回值是1,说明是串口接收中断发生。 5.2 硬件设计本实验需要用到的硬件资源有: 1) UART2 2) PC 电路在 W7500EVB 开发板上默认是已经连接好了的。所以在硬件上不需要动任何东西。 5.3 软件设计在W7500EVB UART工程里,可以看到 main.c 里面编写有如下代码: int main() { uint8_t i = 0,tx_dara[100] = "炜世科技W7500EVB\r\n\t串口试验\r\n"; SystemInit(); /* 系统内部时钟初始化 */ delay_init(); /* 系统滴答时钟配置*/ S_UART_Init(115200); /* 初始化串口通信:115200@8-n-2*/ S_UART_ITConfig(S_UART_IT_FLAG_RXI, ENABLE); NVIC_ClearPendingIRQ(UART2_IRQn); NVIC_EnableIRQ(UART2_IRQn); /*------------------------------------------------------------------ | 炜世科技—WIZnet W7500官方代理商,全程技术支持,价格绝对优势! | -------------------------------------------------------------------*/ while(tx_dara[i] != '\0') { S_UART_SendData(tx_dara[i]); //通过UART2发送 while(S_UART_GetFlagStatus(S_UART_FLAG_TXF)); //判读UART1忙 i++; } while(1) { ; } } 在 W7500x_it.c 里面编写如下代码: void UART2_Handler(void) { uint8_t ReadValue; ReadValue = S_UART_ReceiveData(); S_UART_SendData(ReadValue); //通过UART2发送 S_UART_ClearITPendingBit(S_UART_IT_FLAG_RXI); } 这里开启了UART2的接收中断无论main.c在执行什么操作只要PC向W7500EVB的UART2发送数据就会进入中断服务函数,这个中断会接收PC发送过来的数据,然后在发送回PC。 这里已经对printf的底层函数修改过了所以可以通过printf函数来输出串口数据了 printf(“串口试验\r\n”); 如果需要更改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; int fputc(int ch, FILE *f) { return (UART_SEND_BYTE(ch)); } int fgetc(FILE *f) { return (UART_SEND_BYTE(UART_RECV_BYTE())); } int ferror(FILE *f) { /* Your implementation of ferror */ return EOF; } void _ttywrch(int ch) { UART_SEND_BYTE(ch); } void _sys_exit(int return_code) { label: goto label; /* endless loop */ } #else /****************************************************************/ /* Retarget functions for GNU Tools for ARM Embedded Processors */ /****************************************************************/ #include <sys/stat.h> __attribute__ ((used)) int _write (int fd, char *ptr, int len) { size_t i; for (i=0; i<len;i++) { UART_SEND_BYTE(ptr[i]); // call character output function } return len; } #endif 5.4 下载验证把程序下载到W7500EVB板子,接着打开串口调试工具,设置串口为开发板的 USB 转串口(CH340C 虚拟串口,得根据自己的电脑选择,我的电脑是 COM11,另外,请注意:波特率是 115200),如图5.4.1所示: 图5.4.1 W7500EVB串口试验结果1 可以看出, W7500 的串口数据发送和接受是没问题的,如图5.4.2所示: 图5.4.2 W7500EVB串口试验结果2 |
|