完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
// USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启 USART 接收缓冲区非空中断 // USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启 USART 发送缓冲区空中断 添加总线空闲中断功能的优点: a) 可以准确地判断出串口数据是否接收完毕,不需要额外添加定时器作数据接收完毕超时检测,不仅可以减少了TIM定时器外设 的使用,提高系统性能,而且可以增强程序的可读性(因为使用TIM定时器做超时检测时,需要在TIM定时器中断函数中添加一个 USART_RX_Over的标识符,影响了程序的可读性); 添加总线空闲中断功能的需要注意的地方: a) 在使用串口空闲中断时需要添加读DR位(数据寄存器)空闲中断变量,因为每次触发串口空闲中断时,需要读取对应USART的DR位(数据寄存器)才能清除IDLE(串口空闲空闲标志位)标志位,保证下次执行时不出错,如图下: #include "sys.h" #include "usart.h" #include "config.h" // //如果使用ucos,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "rtthread.h" //ucos 使用 #endif // //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32开发板 //串口1初始化 //正点原子@ALIENTEK //技术william hill官网 :www.openedv.com //修改日期:2012/8/18 //版本:V1.5 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved //******************************************************************************** //V1.3修改说明 //支持适应不同频率下的串口波特率设置. //加入了对printf的支持 //增加了串口接收命令功能. //修正了printf第一个字符丢失的bug //V1.4修改说明 //1,修改串口初始化IO的bug //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方 //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方) //4,修改了EN_USART1_RX的使能方式 //V1.5修改说明 //1,增加了对UCOSII的支持 // // //加入以下代码,支持printf函数,而不需要选择use MicroLIB #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((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } #endif /*使用microLib的方法*/ /* int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t) ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } int GetKey (void) { while (!(USART1->SR & USART_FLAG_RXNE)); return ((int)(USART1->DR & 0x1FF)); } */ #if EN_USART1_RX //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART_RX_BUF_add_cnn[USART_REC_LEN_add_cnn]; //接收缓冲,最大USART_REC_LEN个字节. 添加上协议头 //串口1的缓存数组 USART1 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART_RX_STA=0; //接收状态标记 //串口1的缓存数组 USART2 u8 USART_RX_BUF2[USART_REC_LEN2]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART_RX_STA2=0; //接收状态标记 u8 checkdata1[8]; //检测串口2接收的特定数据数据 u8 checkdata[8]; //检测串口2接收的特定数据数据 u8 fanhuicheckdata[21]; //检测串口2接收的特定数据数据 //串口1队列定义 u8 UART1SendBuff[UART1BuffSize]; //发送数据 u8 UART1ReceBuff[UART1BuffSize]; //接收数据? u16 UART1ReceIn = 0;//接收状态标记数据位 u8 UART1ReceFullFlag = 0;//接收完数据标志位 //串口2队列定义 u8 UART2SendBuff[UART2BuffSize]; //发送数据 u8 UART2ReceBuff[UART2BuffSize]; //接收数据 u16 UART2ReceIn = 0; //接收状态标记数据位 u8 UART2ReceFullFlag = 0; //接收完数据标志位 void uart_init(u32 bound){ //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 #if 1 //Usart1 NVIC 配置 中断接收 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断 #endif //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 } //串口2初始化 void USART2_Configuration(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_InitTypeDef USART_InitStructure;; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//USART2时钟 来自APB1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟 //USART2_TX GPIOA.2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2 //USART2_RX GPIOA.3初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3 //Usart2 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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; //收发模式 USART_Init(USART2, &USART_InitStructure); //初始化串口2 USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //开启串口接收中断 USART_Cmd(USART2, ENABLE); //使能串口2 } //串口1发送一帧数据 void USART1_SendOneData(uint32_t SendOneData) { USART_SendData(USART1, SendOneData); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} } //串口2发送一帧数据 void USART2_SendOneData(uint32_t SendOneData) { USART_SendData(USART2, SendOneData); while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET) {} } //串口2发送一列数据 void USART2_SendUnfixedData(uint32_t *Buffer, uint8_t Length) { uint8_t i; for(i=0;i USART2_SendOneData(*Buffer++); } } //串口1发送一列数据 void USART1_SendUnfixedData(uint32_t *Buffer, uint8_t Length) { uint8_t i; for(i=0;i USART1_SendOneData(*Buffer++); } } //串口1发送一列数据 void USART1_SendUnfixedDatasda(u8 *Buffer, uint8_t Length) { uint8_t i; for(i=0;i USART1_SendOneData(*Buffer++); } } //串口1发送二维数据数据 void USART1_SendUnfixedData2(uint32_t *Buffer, uint8_t x,uint8_t y) { uint8_t i,j; for(i=0;i for(j=0;j USART1_SendOneData(*Buffer++); } } } RxDataType RxDataType_NUM; //定义modbus控制器 #if 1 void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; uint8_t clear = clear; // 用来消除编译器的“没有用到”的提醒 u16 t; u16 len; u16 RxCounter; #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. rt_enter_critical(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // RXNE:读数据寄存器非空 接收中断(接收到的数据必须是0x0d 0x0a结尾) { // GPIO_WriteBit(GPIOB,GPIO_Pin_0 ,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_0)));//LED闪烁辅助观察 Res =USART_ReceiveData(USART1); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { RxDataType_NUM.s[USART_RX_STA&0X3FFF] = Res; RxCounter++; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } // USART_SendData(USART2, 0xaa); // USART_SendData(USART2, Res); // while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET) // switch(USART_RX_STA) // { // case 0: // if(Res==0xAA) // USART_RX_BUF[USART_RX_STA++] = Res; // else // USART_RX_STA = 0; // break; // case 1: // if(Res==0XBB) // USART_RX_BUF[USART_RX_STA++] = Res; // else // USART_RX_STA = 0; // break; // default: // USART_RX_BUF[USART_RX_STA++] = Res; // break; // } // if(USART_RX_STA >= 5) // { // USART_RX_STA = 0; // } // USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除相对应的中断位 清除中断预处理位USART_ClearITPendingBit左移八位是USART_ClearFlag // // USART_ClearFlag(USART1,USART_FLAG_ORE); // if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) // 发送中断 USART_GetITStatus // { // USART_ClearITPendingBit(USART1, USART_IT_TXE); // clear interrupt 清除中断预处理位 // // } // if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)//是否接受到一个字节 // { // RxDataType_NUM.s[RxCounter++] = USART1->DR; // } #if 0 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } } } #endif #if 0 while(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 // printf("rn您发送的消息为:rnrn"); for(t=0;t USART_SendData(USART2, USART_RX_BUF[t]);//向串口1发送数据 // while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } // printf("rnrn");//插入换行 USART_RX_STA=0; } #endif } else if(USART1->SR&(1<<4)) //空闲中断 { clear=USART1->DR; //读DR,清除IDLE位 USART_RX_STA|=0x8000; //接收完成了 //标记完成一帧数据接收 } else if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET) // else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)//是否接受到一帧 //空闲中断 { clear=USART1->SR; clear=USART1->DR;//这两句是清除状态位的,必须加上。如果提示未使用,定义一个uint8_t变量存储返回值即可 RxCounter=0;//一帧数据存储完毕,清零 USART_RX_STA|=0x8000; //接收完成了 USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除空闲中断 } #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. rt_exit_critical(); #endif } #endif //串口2中断服务函数 void USART2_IRQHandler(void) { u8 Res; u16 t; u16 len; #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. rt_enter_critical(); #endif if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART2); //读取接收到的数据 串口2 // USART_SendData(USART2, 0xaa); //将串口2接收到的数据转到串口1 USART_SendData(USART1, Res); // while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET) // switch(USART_RX_STA) // { // case 0: // if(Res==0xAA) // USART_RX_BUF[USART_RX_STA++] = Res; // else // USART_RX_STA = 0; // break; // case 1: // if(Res==0XBB) // USART_RX_BUF[USART_RX_STA++] = Res; // else // USART_RX_STA = 0; // break; // default: // USART_RX_BUF[USART_RX_STA++] = Res; // break; // } // if(USART_RX_STA >= 5) // { // USART_RX_STA = 0; // } // USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除相对应的中断位 清除中断预处理位USART_ClearITPendingBit左移八位是USART_ClearFlag // // USART_ClearFlag(USART1,USART_FLAG_ORE); // if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) // 发送中断 USART_GetITStatus // { // USART_ClearITPendingBit(USART1, USART_IT_TXE); // clear interrupt 清除中断预处理位 发送寄存器 // // } if((USART_RX_STA2&0x8000)==0)//接收未完成 { if(USART_RX_STA2&0x4000)//接收到了0x0d { if(Res!=0x0a)USART_RX_STA2=0;//接收错误,重新开始 else USART_RX_STA2|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA2|=0x4000; else { USART_RX_BUF2[USART_RX_STA2&0X3FFF]=Res ; USART_RX_STA2++; if(USART_RX_STA2>(USART_REC_LEN2-1))USART_RX_STA2=0;//接收数据错误,重新开始接收 } } } // while(USART_RX_STA&0x8000) // { // len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 // // printf("rn您发送的消息为:rnrn"); // for(t=0;t // USART_SendData(USART2, USART_RX_BUF[t]);//向串口1发送数据 // // while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 // } // // printf("rnrn");//插入换行 // USART_RX_STA=0; // } } #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. rt_exit_critical(); #endif } /************************ 原串口中断处理函数 **********************/ #if 0 u8 Res;//数据暂存 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断 { Res =USART_ReceiveData(USART2); //读取接收到的数据 switch(UART2ReceIn)//读取接收到的数据有几位 每一位对应的数据协议校验 { case 0: if(Res==0xAA) UART2ReceBuff[UART2ReceIn++] = Res; else UART2ReceIn = 0; break; case 1: if(Res==0xBB) UART2ReceBuff[UART2ReceIn++] = Res; else UART2ReceIn = 0; break; case 2://此处为判断 {UART2ReceBuff[UART2ReceIn++] = Res; checkdata[0]=UART2ReceBuff[2]; // send_number_data(1); } break; case 3://此处为判断数据 {UART2ReceBuff[UART2ReceIn++] = Res; checkdata[1]=UART2ReceBuff[3]; //接收到 // crc16_data1[3]= UART1ReceBuff[3]; } break; case 5: if(Res==0xCC) UART2ReceBuff[UART2ReceIn++] = Res; else UART2ReceIn = 0; break; case 6: if(Res==0xDD) UART2ReceBuff[UART2ReceIn++] = Res; else UART2ReceIn = 0; break; default: UART2ReceBuff[UART2ReceIn++] = Res; break; } if(UART2ReceIn >= 6) { UART2ReceFullFlag = 1; //数据完整接受完 UART2ReceIn = 0; } USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清除相对应的中断位 清除中断预处理位USART_ClearITPendingBit左移八位是USART_ClearFlag } else if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET) // 发送中断 USART_GetITStatus { USART_ClearITPendingBit(USART2, USART_IT_TXE); // clear interrupt 清除中断预处理位 } /* u8 Res; #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntEnter(); #endif if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART2); //读取接收到的数据USART_ReceiveData if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { UART2ReceBuff[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } } } } #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntExit(); #endif */ #endif /* 重映射串口1到rt_kprintf */ void rt_hw_console_output(const char *str) { rt_enter_critical();//锁定线程调度 /*字符串结束*/ while (*str!=' |