#include "usart.h" #include "delay.h" ////////////////////////////////////////////////////////////////////////////////// //如果使用os,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h" //os 使用 #endif ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32F407开发板 //串口3初始化 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2017/4/6 //版本:V1.5 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved //******************************************************************************** //V1.0修改说明 ////////////////////////////////////////////////////////////////////////////////// //加入以下代码,支持printf函数,而不需要选择use MicroLIB //#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART3->SR&0X40)==0);//循环发送,直到发送完毕 USART3->DR = (u8) ch; return ch; } #endif //串口2中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. u16 USART2_RX_STA=0; //接收状态标记 UART_HandleTypeDef huart2; //USART3句柄(用于RS485) u8 usart2_aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲 #if EN_USART3_RX //如果使能了接收 //串口3中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. UART_HandleTypeDef huart3; //USART3句柄(用于RS485) //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART3_RX_STA=0; //接收状态标记 u8 usart3_aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲 UART_HandleTypeDef UART2_Handler; //UART句柄 UART_HandleTypeDef UART3_Handler; //UART句柄 //****************************************** //初始化IO 串口2 //bound:波特率 //****************************************** void uart2_init(u32 bound) { //UART 初始化设置 UART3_Handler.Instance=USART2; //USART1 UART3_Handler.Init.BaudRate=bound; //波特率 UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式 UART3_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位 UART3_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位 UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控 UART3_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式 HAL_UART_Init(&UART2_Handler); //HAL_UART_Init()会使能UART3 HAL_UART_Receive_IT(&UART2_Handler, (u8 *)usart2_aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 } //****************************************** //初始化IO 串口3 //bound:波特率 //****************************************** void uart3_init(u32 bound) { //UART 初始化设置 UART3_Handler.Instance=USART3; //USART1 UART3_Handler.Init.BaudRate=bound; //波特率 UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式 UART3_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位 UART3_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位 UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控 UART3_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式 HAL_UART_Init(&UART3_Handler); //HAL_UART_Init()会使能UART3 HAL_UART_Receive_IT(&UART3_Handler, (u8 *)usart3_aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 } //UART底层初始化,时钟使能,引脚配置,中断配置 //此函数会被HAL_UART_Init()调用 //huart:串口句柄 void HAL_UART_MspInit(UART_HandleTypeDef *huart) { //GPIO端口设置 GPIO_InitTypeDef GPIO_Initure; if(huart->Instance==USART2)//如果是串口2,进行串口2 MSP初始化 { __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟 __HAL_RCC_USART2_CLK_ENABLE(); //使能USART3时钟 GPIO_Initure.Pin=GPIO_PIN_2; //PA2 usart2_tx GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速 HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA2 GPIO_Initure.Pin=GPIO_PIN_3; //PA3 GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式! HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA2 __HAL_UART_ENABLE_IT(&UART2_Handler,UART_IT_RXNE);//开启接收中断 HAL_NVIC_EnableIRQ(USART2_IRQn); //使能USART3中断通道 HAL_NVIC_SetPriority(USART2_IRQn,1,1); //抢占优先级3,子优先级3 } if(huart->Instance==USART3)//如果是串口3,进行串口3 MSP初始化 { __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟 __HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟 __HAL_RCC_USART3_CLK_ENABLE(); //使能USART3时钟 GPIO_Initure.Pin=GPIO_PIN_10; //PB10 usart3_tx GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB10 GPIO_Initure.Pin=GPIO_PIN_11; //PB11 GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式! HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB11 GPIO_Initure.Pin = GPIO_PIN_13; //485 发送接收 GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Initure.Pull = GPIO_NOPULL; GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC, &GPIO_Initure); #if EN_USART3_RX __HAL_UART_ENABLE_IT(&UART3_Handler,UART_IT_RXNE);//开启接收中断 HAL_NVIC_EnableIRQ(USART3_IRQn); //使能USART3中断通道 HAL_NVIC_SetPriority(USART3_IRQn,2,2); //抢占优先级3,子优先级3 #endif Usart_TX_Set(0); //设置为接收模式 } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance==USART2)//如果是串口2 { if((USART2_RX_STA&0x8000)==0)//接收未完成 { if(USART2_RX_STA&0x4000)//接收到了0x0d { if(usart2_aRxBuffer[0]!=0x0a)USART2_RX_STA=0;//接收错误,重新开始 else USART2_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(usart2_aRxBuffer[0]==0x0d)USART2_RX_STA|=0x4000; else { USART2_RX_BUF[USART2_RX_STA&0X3FFF]=usart2_aRxBuffer[0] ; USART2_RX_STA++; if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收 } } } } if(huart->Instance==USART3)//如果是串口3 { if((USART3_RX_STA&0x8000)==0)//接收未完成 { if(USART3_RX_STA&0x4000)//接收到了0x0d { if(usart3_aRxBuffer[0]!=0x0a)USART3_RX_STA=0;//接收错误,重新开始 else USART3_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(usart3_aRxBuffer[0]==0x0d)USART3_RX_STA|=0x4000; else { USART3_RX_BUF[USART3_RX_STA&0X3FFF]=usart3_aRxBuffer[0] ; USART3_RX_STA++; if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收 } } } } } //串口2中断服务程序 void USART2_IRQHandler(void) { u32 timeout=0; #if SYSTEM_SUPPORT_OS //使用OS OSIntEnter(); #endif HAL_UART_IRQHandler(&UART2_Handler); //调用HAL库中断处理公用函数 timeout=0; while (HAL_UART_GetState(&UART2_Handler) != HAL_UART_STATE_READY)//等待就绪 { timeout++;////超时处理 if(timeout>HAL_MAX_DELAY) break; } timeout=0; while(HAL_UART_Receive_IT(&UART2_Handler, (u8 *)usart2_aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1 { timeout++; //超时处理 if(timeout>HAL_MAX_DELAY) break; } #if SYSTEM_SUPPORT_OS //使用OS OSIntExit(); #endif } //串口3中断服务程序 void USART3_IRQHandler(void) { u32 timeout=0; #if SYSTEM_SUPPORT_OS //使用OS OSIntEnter(); #endif HAL_UART_IRQHandler(&UART3_Handler); //调用HAL库中断处理公用函数 timeout=0; while (HAL_UART_GetState(&UART3_Handler) != HAL_UART_STATE_READY)//等待就绪 { timeout++;////超时处理 if(timeout>HAL_MAX_DELAY) break; } timeout=0; while(HAL_UART_Receive_IT(&UART3_Handler, (u8 *)usart3_aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1 { timeout++; //超时处理 if(timeout>HAL_MAX_DELAY) break; } #if SYSTEM_SUPPORT_OS //使用OS OSIntExit(); #endif } #endif //****************************************** //RS485模式控制. //Ren:1,接收;0,发送. //****************************************** void Usart_TX_Set(uint8_t Ren) { uint8_t i; i=Ren; if(i==0) { PCout(13)=0; } else { PCout(13)=1; } } //****************************************** //RS485发送字符串. //****************************************** void Usart_Send_Str_Data(char *str) { Usart_TX_Set(1); //设置为发送模式 delay_us(50); printf(str); Usart_TX_Set(0); //设置为接收模式 delay_us(50); } //****************************************** //RS485发送len个字节. //buf:发送区首地址 //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节) //****************************************** void Usart_Send_Data(uint8_t *buf,uint8_t len) { Usart_TX_Set(0); //设置为发送模式 delay_ms(100); HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_1); // HAL_UART_Transmit(&huart3,buf,len,1000);//串口3发送数据 Usart_TX_Set(1); //设置为接收模式 delay_ms(50); } //中断缓存串口数据 #define UART_BUFF_SIZE 1024 volatile uint16_t uart_p = 0; uint8_t uart_buff[UART_BUFF_SIZE]; /* void RS485_IRQHandler(void) { if(uart_p