【CW32饭盒派开发板试用体验】+USART+ESP8266测试
- 硬件资源介绍
本次实验主要测试了USART和ESP8266 AT命令功能。上位机串口助手通过USART3(PA9,PA10)与主板进行通讯,在USART3的中断函数中,将数据转发给USART2(PA2,PA3)的ESP8266,这样可以测试中断函数接收数据和解析数据是否正确。数据接收完毕是通过时间来判断,超出20ms则接收完毕。结尾附例程
ESP8266模块用的是正点原子的,资料在论坛中
http://www.openedv.com/docs/modules/iot/atk-esp.html?highlight=esp
- 测评流程
- 编写USART2和USART3驱动代码和中断服务函数。
- 重定向printf(uint8_t * str)和u2_printf(uint8_t* str)
- 处理数据显示乱码问题,优化前后台代码。
- 测试ESP8266 AT命令,链接WIFI并上位机与下位机实现收据收发。
- 在仿真的时候,串口助手会很快接收到数据,代码还没有运行就有初始化的数据打印出来。运行后相当于打印了两次,有没有朋友遇到这种情况。解释下。
- 代码介绍
- 代码结构如上图,目前将USART代码单独做成模块进行开发。
- Usart初始化部分
void usart_init(int port)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
if(port == 3)
{
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_UART3, ENABLE);
RCC_AHBPeriphClk_Enable( RCC_AHB_PERIPH_GPIOA, ENABLE);
PA09_AFx_UART3TXD();
PA10_AFx_UART3RXD();
GPIO_InitStructure.Pins = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_PIN_10;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
}
if(port == 2)
{
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_UART2, ENABLE);
RCC_AHBPeriphClk_Enable( RCC_AHB_PERIPH_GPIOA, ENABLE);
PA02_AFx_UART2TXD();
PA03_AFx_UART2RXD();
GPIO_InitStructure.Pins = GPIO_PIN_2;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_PIN_3;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
}
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_Over = USART_Over_16;
USART_InitStructure.USART_Source = USART_Source_PCLK;
USART_InitStructure.USART_UclkFreq = 64000000;
USART_InitStructure.USART_StartBit = USART_StartBit_FE;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
if(port == 3)
{
USART_Init(CW_UART3, &USART_InitStructure);
USART_ITConfig(CW_UART3, USART_IT_RC, ENABLE);
NVIC_SetPriority(UART3_IRQn, 0);
NVIC_EnableIRQ(UART3_IRQn);
}
if(port == 2)
{
USART_Init(CW_UART2, &USART_InitStructure);
USART_ITConfig(CW_UART2, USART_IT_RC, ENABLE);
NVIC_SetPriority(UART2_IRQn, 0);
NVIC_EnableIRQ(UART2_IRQn);
}
}
- U2_printf()函数,这个函数也是以前一直使用的。方便直接发送string
void u2_printf(char* fmt,...)
{
int i ;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART2_TX_BUF,fmt,ap);
va_end(ap);
strlen(fmt);
for(i = 0; i< strlen(fmt);i++)
{
USART_SendData(CW_UART2,fmt[i]);
while(USART_GetFlagStatus(CW_UART2,USART_FLAG_TXE)==RESET);
USART_ClearFlag(CW_UART2,USART_FLAG_TXE);
}
}
- USART中断服务函数,串口2主要处理ESP8266接收到的数据,串口3为中转和打印用。
void UART2_IRQHandler(void)
{
unsigned char TxRxBuffer;
if(USART_GetITStatus(CW_UART2, USART_IT_RC) != RESET)
{
USART_ClearITPendingBit(CW_UART2, USART_IT_RC);
TxRxBuffer = USART_ReceiveData_8bit(CW_UART2);
USART2_TEMP_RX_BUF[USART2_TEMP_idx] = TxRxBuffer;
USART2_TEMP_idx++;
if(USART2_TEMP_idx >=1000)
{
USART2_TEMP_idx = 0;
}
MS_rcv_num = 0;
}
}
void UART3_IRQHandler(void)
{
unsigned char TxRxBuffer;
if(USART_GetITStatus(CW_UART3, USART_IT_RC) != RESET)
{
USART_ClearITPendingBit(CW_UART3, USART_IT_RC);
TxRxBuffer = USART_ReceiveData_8bit(CW_UART3);
USART_SendData(CW_UART2,TxRxBuffer);
}
}
- 滴答处理任务,主要用于判断usart接收是否超时。1KHZ任务。
void SysTick_Handler(void)
{
uwTick += uwTickFreq;
if(USART2_RX_STA == 0 && USART2_TEMP_idx >0 )
MS_rcv_num++;
if(MS_rcv_num == 20)
{
memset(USART2_RX_BUF,0,1000);
memcpy(USART2_RX_BUF,USART2_TEMP_RX_BUF,USART2_TEMP_idx);
USART2_idx = USART2_TEMP_idx;
USART2_TEMP_idx = 0;
memset(USART2_TEMP_RX_BUF,0,1000);
USART2_RX_STA = 1;
MS_rcv_num= 0;;
}
}
//系统滴答定时器,用于处理ms任务。
/* USER CODE END SysTick_IRQn */
}
- 上面说的乱码问题,主要就是数组接收完数据后,没有清理干净,之前的数据无法覆盖,打印的时候又刷出来了,memset处理了一下,后面再优化代码。
- 例程下载
下载后,验证AT命令响应均正常。数据接收和处理也无问题,本次实验内容结束,接下来通过下位机配置ESP8266进行通讯测试,移植MPU6050驱动。
附代码:*附件:实验十 综合实验.zip