M0516LDN串口接收超时中断触发方式不触发怎么办

查看: 5531|回复: 3
串口超时判断方式接收未知长度数据(寄存器操作)
主题帖子精华
初级会员, 积分 91, 距离下一级还需 109 积分
在线时间0 小时
刚学stm32不久,前段在原子的程序基础上改了个串口超时判断接收未知数据的函数,欢迎大家批评,新手+菜鸟,拍砖请留情~~~~~
程序的功能:串口发送六位控制码123456,控制LED0的亮灭。原子给的例程接收的数据以回车键作为结束标志,下面改过之后就不用加回车了,更接近实际数据接收的场景。定时器只是改了下原子的中断服务函数,别的都一样。
usart.c串口中断处理函数:&
u8 USART_RX_BUF[64]; & & //接收缓冲,最大64个字节.
u8 res=0;&
u8 i=0,Rec_L
//Rec_Len为接收到的字符个数
u8 Rec_Over_Flag=0;
u8 RxTimeout=3;
//串口接收超时;
void USART1_IRQHandler(void)
if(USART1-&SR&(1&&5))//接收到数据
if(RxTimeout==0)
Rec_Len=i;
Rec_Over_Flag=1;
RxTimeout=3; & //定时器每隔10ms中断一次,3次的时间为30ms,超过30ms无数据发送就认定该次发送结束
USART_RX_BUF[i++]=USART1-&DR;
timer.c定时器函数
void TIM3_IRQHandler(void)
if(TIM3-&SR&0X0001)//溢出中断
if(RxTimeout&0)
RxTimeout--;
if(RxTimeout==0)
LED1=!LED1;
& & //RxTimeout等于0,变换LED1表明该次发送结束
TIM3-&SR&=~(1&&0);//清除中断标志位
main.c主函数&
int main(void)
extern u8 i,Rec_Len,Rec_Over_F
u8 Password[7]="123456";
u8 Tishi1[]="操作码长度不对";
u8 Tishi2[]="操作码不正确";
u8 Tishi3[]="指令成功执行!";
u16 times=0; &
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);
& & //延时初始化&
uart_init(72,9600);
//串口初始化为9600
LED_Init();
//初始化与LED连接的硬件接口&
Timerx_Init(100,7199); &//10kHz的技术频率,计数到100为10ms
if(Rec_Over_Flag==1)
len=Rec_L//得到此次接收到的数据长度
if(len!=0x06)
Putstrings(Tishi1);
else &// len等于6
for(t=0;t&t++)
if(USART_RX_BUF[t]!=Password[t])
Putstrings(Tishi2);
else if(t==(len-1))
Putstrings(Tishi3);
LED0=!LED0;
Rec_Over_Flag=0;
if(times%30==0)LED1=!LED1;//闪烁LED,提示系统正在运行.
if(times%30==0)RxTimeout--;&
delay_ms(10);
//------------输出字符串到串口-------------------
void Putstrings(u8 *ptr)
while(*ptr!='\0')
USART1-&DR=*ptr++;
while((USART1-&SR&0X40)==0);//等待发送结束
USART1-&DR='\n';
刚刚发现程序有点问题,发送3次”123456“,之后再发3次“1234567”,为什么残留有上次的指令码呢?谁能指点下,多谢啦!
e88f741fc2fdb4d00a2e8_610.jpg (0 Bytes, 下载次数: 0)
22:54 上传
5d805a660caae1bff71af8a7dcebb79f_780.jpg (0 Bytes, 下载次数: 0)
22:54 上传
主题帖子精华
金钱104461
在线时间648 小时
中断超时法我们的蓝牙模块用的代码,就有。
你参考下:/posts/list/12486.htm
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子
主题帖子精华
初级会员, 积分 91, 距离下一级还需 109 积分
在线时间0 小时
回复【2楼】正点原子:
---------------------------------
好的,我去看看~~
主题帖子精华
新手上路, 积分 39, 距离下一级还需 11 积分
在线时间0 小时
看了楼主的程序,觉得楼主所说的bug可能跟下面这段程序有关
void USART1_IRQHandler(void)
if(USART1-&SR&(1&&5))//接收到数据
if(RxTimeout==0)
Rec_Len=i;
Rec_Over_Flag=1;
RxTimeout=3; & //定时器每隔10ms中断一次,3次的时间为30ms,超过30ms无数据发送就认定该次发送结束
USART_RX_BUF[i++]=USART1-&DR;
从这段函数来看,要使Rec_Over_Flag置1的前提是满足if(USART1-&SR&(1&&5)),因为if(RxTimeout==0)嵌套在内,也就是说要有接收才可能有Rec_Over_Flag的置位,而Rec_Over_Flag置1的前提却是30ms内没有接收,这就造成了矛盾,所以楼主用串口发送字符串的时候,打印出来的字符串实际上是上一次发送的字符串,我估计你这个程序在刚启动的时候,第一次发送字符串时,PC上是不会打印任何东西的。
以上是个人意见,有错请喷。
Powered bystm32&usart接收中断超时处理
void NVIC_Configuration(void)
NVIC_InitTypeDef NVIC_InitS
#ifdef& VECT_TAB_RAM&
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
NVIC_SetVectorTable(NVIC_VectTab_FLASH,
&&& #endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel =&
USART1_IRQn;;&
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
void GPIO_Configuration(void)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
void USART_Configuration(void)
&USART_InitStructure.USART_BaudRate =
9600;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//波特率9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits =
USART_StopBits_1;&&&&&&&&&&&&&&&&&
//1位停止字节
USART_InitStructure.USART_Parity =
USART_Parity_No;&&&&&&&&&&&&&&&&&&&
//无奇偶校验
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_N//无流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx |
USART_Mode_Tx;//打开Rx接收和Tx发送功能
USART_Init(USART1,
&USART_InitStructure);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
USART_Cmd(USART1,
ENABLE);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//启动串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
&USART_ITConfig(USART1, USART_FLAG_TC,
RCC_Configuration(void)&&&
//时钟初始化函数
&&& ErrorStatus
HSEStartUpS&&&&
//等待时钟的稳定
RCC_DeInit();&&&&&&&&
//时钟管理重置
RCC_HSEConfig(RCC_HSE_ON);&&&&&
//打开外部晶振
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部晶振就绪
(HSEStartUpStatus == SUCCESS)
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//flash读取缓冲,加速
FLASH_SetLatency(FLASH_Latency_2); //flash操作的延时
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB使用系统时钟
RCC_PCLK2Config(RCC_HCLK_Div2);&
//APB2(高速)为HCLK的一半
RCC_PCLK1Config(RCC_HCLK_Div2);&
//APB1(低速)为HCLK的一半
//注:AHB主要负责外部存储器时钟。PB2负责AD,I/O,高级TIM,串口1。APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM。
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
&&//PLLCLK = 8MHz * 9 = 72
RCC_PLLCmd(ENABLE);&&&&
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) ==
RESET){};//等待PLL启动
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//将PLL设置为系统时钟源
while (RCC_GetSYSCLKSource() != 0x08){}//等待系统时钟源的启动
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|
RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA, ENABLE );
SysTick_Config()函数的参数配置,SysTick时钟配置
SysTick_Configuration(void)
&&&&&&&&&&&
&&&&&&&&&&&&if
(SysTick_Config((SystemCoreClock) /
10))&&&&//&&&&
1/10s=100ms
&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&while (1);
&&&&&&&&&&&&}
&NVIC_SetPriority(SysTick_IRQn, 0x0);
SysTick_Config(SystemFrequency
函数的形参就是systick重装定时器的值。
systck计数频率为每秒次,所以7200000次就是1/10秒,也就是100ms。
SysTick是1个24bit递减计数器,通过对SysTick控制与状态寄存器的设置,可选择HCLK时钟(72M)或HCLK的8分频(9M,缺省是这个)作为SysTick的时钟源。
SysTick的重装寄存器决定了定时器频率。
若SysTick的时钟源是72M,&&
SystemFrequency = Hz
SysTick_Config(SystemFrequency / 1000);
就是1ms时基。
1/1000 s=1ms
void USART1_IRQHandler(void)
&&& uint8_t
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET)
RxTimeOut=3;//字符串超时等待时间;3毫秒;
i = USART_ReceiveData(USART1);//接收下一个字符
data[f]=i;
&&&&&&&USART_SendData(USART1,data[f]);&
&&&&&&&while(USART_GetFlagStatus(USART1,
USART_FLAG_TXE) == RESET) {};&
if (f==32) {f=33;flag=1;}
//32个数据接收完成,flag置1,f进入空闲状态&
if(USART_GetITStatus(USART1, USART_IT_RXNE) == RESET)
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
void SysTick_Handler(void)
if(RxTimeOut&0)&&RxTimeOut--;
&else&&&&f=33;
//超时进入空闲状态
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。串口接收中断 - 单片机/MCU论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
串口接收中断
09:18:04  
///////////////////////////////////////////////////////////////////////
// 接收和发送中断
///////////////////////////////////////////////////////////////////////
void isr_UART(void) interrupt 4 using 1
& && &unsigned char len,
& && &unsigned int j=0;
& && &if(RI)
& && && &&&len=SBUF;
& && && &&&RI=0;& & //清除接收中断标志
& && && &&&for(i=0;i&i++)
& && && & {
& && && && && &&&while(!RI)
& && && && && & {
& && && && && && && && &j++;
& && && && && && && && &if(j&1000)
& && && && && && && && &{
& && && && && && && && && &&&
& && && && && && && && &}& &&&//防止误操作命令发生
& && && && && & }
& && && && && & if(j&1000)
& && && && && & {
& && && && && && && &RevBuffer[i]=SBUF; //RevBuffer[0]里面放的是收到命令字
& && && && && && && &RI=0;
& && && && && && && &j=0;
& && && && && & }
& && && && && &else
& && && && && &{
& && && && && && && &
& && && && && &}
& && && &}
& && && &if(i==len)
& && && &{
& && && && && & REN=0;& &&&//允许/禁止串行接收控制位。REN=0禁止串行接收
& && && && && & CmdValid=1; //CmdValid=1表示命令合法
& && && &}
& & else if(!RI && TI)
& && && &&&TI=0;
& && && && &len=RevBuffer[0];
& && && && &for(i=0;i&len+1;i++)
& && && && &{
& && && && && &&&SBUF=RevBuffer[i];
& && && && && &&&while(!TI);& &//在同级中断中不会再次发生中断
& && && && && & TI=0;& &
& && && && &}
& && && &&&REN=1;
这段程序刚开始len = SBUF,究竟是每来一个字节都这样,还是只执行一次?还有进入if(RI)后,RI= 0,那while(!RI)不是一直成立吗?纠结中......求大神指教
09:46:59  
if(RI)//如果接收到数据
& && && &&&len=SBUF;//读取第一个字节,这里代表这次传输共有多少字节
& && && &&&RI=0;& & //清除接收中断标志
& && && &&&for(i=0;i&i++)//开始有效数据接收,接收len个字节。连续读计算机串口缓存里发送的数据
& && && & {
& && && && && &&&while(!RI)//等待单片机接收移位寄存器载满即,接收到一字节
& && && && && & {
& && && && && && && && &j++;//这个while里的作用就是超时放弃接收。
& && && && && && && && &if(j&1000)
& && && && && && && && &{
& && && && && && && && && &&&
& && && && && && && && &}& &&&//防止误操作命令发生
& && && && && & }
最好再在进入那个for(i=0;i&i++)接收前,关掉ES中断。完毕后打开。
09:49:28  
len=SBUF;是建立一次连接执行一次。一次连接会有len字节数据传来。
22:38:48  
学习了。。。。。。。。。。。。。。。{:3:}{:3:}{:3:}
10:41:37  
if(RI)//如果接收到数据
& && && &&&len=SBUF;//读取第一个字节,这里代表这次传输共有多少字节
刚开始是接收了一个字节数据,然后进入if(RI),但是这个if语句没执行完还可以继续接收数据吗?
CellWise周军
15个问题&&&&&&&&3010个浏览
13个问题&&&&&&&&16062个浏览
6个问题&&&&&&&&6336个浏览
Powered by}

我要回帖

更多关于 中断触发方式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信