关于STM32空闲中断

有一次做一个东西,为了尽量不占用CPU的处理数据时间,所以就使用DMA接收串口的数据,但是呢问题来了.,,,,,怎么样才能确定接收到了一条完整的数据了,,我们都知道只要打开DMA

那家伙就不停的把接收的数据放到我们指定的地方.

只要接收到一条完整的数据我就该去处理了

关于空闲中断,,,就是说每接收到一条完整的数据就会置位空闲标志位,我们只需要判断空闲标志位是否置一,,就能知道是不是接收到了一条完整的数据

用空闲中断的好处就是,,对于以前我写程序通信都会在数据的后面加上尾,,然后另一个接收的单片机通过判断数据的尾来确定是不是一条完整的数据,,,有了空闲中断就不需要在给数据加上尾了,,,,,

直接程序吧

u8  Usart1_RX_Cop[1024]={0};//串口2备用接收缓冲,最大 1024 个字节.u8  Usart1_RX_BUF[1024]={0};//串口1接收缓冲,最大 1024 个字节.u16 Usart1_REC_Cnt =0;//串口1接收的数据个数u16 Usart1_Current_Cnt =0;//串口1当前接收的数据个数u16 Usart1_Current_cnt =0;//串口1当前接收的数据个数u8  Usart1_AT_flage =0;//串口1接收完成标志位u8  Usart2_RX_Cop[1024]={0};//串口2备用接收缓冲,最大 1024 个字节.u8  Usart2_RX_BUF[1024]={0};//串口2接收缓冲,最大 1024 个字节.u16 Usart2_REC_Cnt =0;//串口2接收的数据个数u16 Usart2_Current_Cnt =0;//串口2当前接收的数据个数u16 Usart2_Current_cnt =0;//串口2当前接收的数据个数u8  Usart2_AT_flage =0;//串口2接收完成标志位u8  Usart3_RX_BUF[1024]={0};//串口3接收缓冲,最大 1024 个字节.u16 Usart3_REC_Cnt =0;//串口3接收的数据个数u8  Usart3_AT_flage =0;//串口3接收完成标志位u8 Free_Read_Rst=0;//读DR清除空闲中断

voidUSART123_Init(uint32_t bound_1,uint32_t bound_2,uint32_t bound_3)

{

USART_InitTypeDef USART_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB1Periph_USART3, ENABLE);//使能USART2,USART3时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO , ENABLE);//USART1_TX  PA9GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;;

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure);//USART1_RX  PA10GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING ;

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;

GPIO_Init(GPIOA,&GPIO_InitStructure);//USART2_TX  GPIOA.2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PA.2GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//USART2_RX      GPIOA.3初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//USART3_TX  GPIOB.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PB10GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure);//USART3_RX      GPIOB.11初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate=bound_1;

USART_InitStructure.USART_WordLength=USART_WordLength_8b;

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);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口1总线空闲中断USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启串口2总线空闲中断USART_InitStructure.USART_BaudRate=bound_2;

USART_Init(USART2,&USART_InitStructure);

USART_InitStructure.USART_BaudRate=bound_3;

USART_Init(USART3,&USART_InitStructure);

USART_Cmd(USART1, ENABLE);

USART_Cmd(USART2, ENABLE);

USART_Cmd(USART3, ENABLE);

}

/********************串口 1 中断服务程序**********************/voidUSART1_IRQHandler(void)

{if(USART_GetITStatus(USART1, USART_IT_RXNE) !=RESET) //正常情况下进入这个接收

{

USART_ClearITPendingBit(USART1, USART_FLAG_ORE);

USART_ClearITPendingBit(USART1,USART_IT_ORE);//清除中断标志Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);//读取接收到的数据Usart1_REC_Cnt++;

}elseif(USART_GetITStatus(USART1,USART_IT_IDLE) ==SET)//传输完一条完整的数据就会进入这个

{

Free_Read_Rst= USART1->DR;//清USART_IT_IDLE标志Usart1_AT_flage =1;//接收到一条完整的数据Usart1_Current_Cnt = Usart1_REC_Cnt;//复制接收到的数据个数Usart1_REC_Cnt =0;//清零接收的个数}

}

主函数循环里只需要......

先说一点:单片机的串口可以接收任意波特率的数据,你所写的9600意思是以这个波特率发送....

其实昨天才发现这家伙真的太准确了,,准确到如果碰见通信中速率如果不是设置的波特率,就是说通信的速率慢了不是(我上面设置的波特率是9600)1/9600(S)发过来一位数据了,低于了这个值假设是2400吧!接受到一位数据后如果1/9600(s)后没有接收到数据,那么这家伙也会进空闲中断.......因为你是设置的9600,,,,那么在1/9600(s)后理应接收到下一位数据....而其实是在1/2400(S)后才会接收到另一位数据.....如果能把空闲中断的检测时间降到满足的要求就好了....

所以嘛,,,,,自己写个别这么苛刻的,昨天写好了,不过呢今天主要是把自己遇到的问题说一下

其实思路都知道

串口接收的时候打开一个定时器,并且只要接收到数据就清零一个变量,这个变量是在定时器里面执行自加一操作,,

如果串口一段时间(空闲中断的检测时间)不接收数据了这个变量就能自加到我们设置的数,然后关掉定时器,置位接收完成标志位,...

直接上程序

/********************串口 1 中断服务程序**********************/voidUSART1_IRQHandler(void)

{if(USART_GetITStatus(USART1, USART_IT_RXNE) !=RESET)

{

USART_ClearITPendingBit(USART1, USART_FLAG_ORE);

USART_ClearITPendingBit(USART1,USART_IT_ORE);//清除中断标志Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);//读取接收到的数据Usart1_REC_Cnt++;

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE );//打开定时器开始计时Time2_cnt =0;//清零计数}

}

voidtimer_config(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/*Resets the TIM2*/TIM_DeInit(TIM2);//设置了时钟分割。TIM_TimeBaseStructure.TIM_ClockDivision =0;//选择了计数器模式。TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;//初值TIM_TimeBaseStructure.TIM_Period =10;//定时时间1ms进一次//设置了用来作为 TIMx 时钟频率除数的预分频值。72M / 7099+1 = 0.01MTIM_TimeBaseStructure.TIM_Prescaler =7199;//TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);/*Enables the TIM2 counter*/TIM_Cmd(TIM2, ENABLE);/*Enables the TIM2 Capture Compare channel 1 Interrupt source*/TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );

}

voidTIM2_IRQHandler(void)

{if(TIM_GetITStatus(TIM2, TIM_IT_Update) ==SET)

{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);if(Time2_cnt<100)//防止累加循环过去

{

Time2_cnt++;

}if(Time2_cnt>3)//空闲时间大于约3毫秒

{

TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );//关闭定时器---注意千万不要放到主函数里面关,,,,大家可以试一试会出现什么问题.....Usart1_AT_flage =1;//接收完成标志位置一

Usart1_Current_Cnt=Usart1_REC_Cnt;//赋值接收的数据个数

Usart1_REC_Cnt=0;//清零接收的数据个数      }

}

然后昨天又写了一个两个串口的,因为用了两个串口做数据转换(用的串口1和串口3),,,,其实其中一个也可以用空闲中断,,但是担心数据传输过程中万一速率有所变化,,,,,,,,完蛋啦

uint8_t  Usart1_TimeFlage =0;//串口1空闲变量允许累加标志uint16_t Usart1_IdealTime =0;//串口1空闲累加变量uint8_t  Usart3_TimeFlage =0;//串口3空闲变量允许累加标志uint16_t Usart3_IdealTime =0;//串口3空闲累加变量u8  Usart1_RX_Cop[1024]={0};//串口2备用接收缓冲,最大 1024 个字节.u8  Usart1_RX_BUF[1024]={0};//串口1接收缓冲,最大 1024 个字节.u16 Usart1_REC_Cnt =0;//串口1接收的数据个数u16 Usart1_Current_Cnt =0;//串口2当前接收的数据个数u16 Usart1_Current_cnt =0;//串口2当前接收的数据个数u8  Usart1_AT_flage =0;//串口1接收完成标志位u8  Usart2_RX_Cop[1024]={0};//串口2备用接收缓冲,最大 1024 个字节.u8  Usart2_RX_BUF[1024]={0};//串口2接收缓冲,最大 1024 个字节.u16 Usart2_REC_Cnt =0;//串口2接收的数据个数u16 Usart2_Current_Cnt =0;//串口2当前接收的数据个数u16 Usart2_Current_cnt =0;//串口2当前接收的数据个数u8  Usart2_AT_flage =0;//串口2接收完成标志位u8  Usart3_RX_Cop[1024]={0};//串口2备用接收缓冲,最大 1024 个字节.u8  Usart3_RX_BUF[1024]={0};//串口2接收缓冲,最大 1024 个字节.u16 Usart3_REC_Cnt =0;//串口2接收的数据个数u16 Usart3_Current_Cnt =0;//串口2当前接收的数据个数u16 Usart3_Current_cnt =0;//串口2当前接收的数据个数u8  Usart3_AT_flage =0;//串口2接收完成标志位

voidtimer3_config(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/*Resets the TIM2*/TIM_DeInit(TIM3);//设置了时钟分割。TIM_TimeBaseStructure.TIM_ClockDivision =0;//选择了计数器模式。TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;//初值TIM_TimeBaseStructure.TIM_Period =10;//定时时间1Ms进一次//设置了用来作为 TIMx 时钟频率除数的预分频值。72M / 7099+1 = 0.01MTIM_TimeBaseStructure.TIM_Prescaler =7199;//TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

TIM_ClearITPendingBit(TIM3, TIM_IT_Update);/*Enables the TIM2 counter*/TIM_Cmd(TIM3, ENABLE);/*Enables the TIM2 Capture Compare channel 1 Interrupt source*/TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE );

}

voidTIM3_IRQHandler(void)

{if(TIM_GetITStatus(TIM3, TIM_IT_Update) ==SET)

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update);if(Usart1_TimeFlage ==1)//开始累加空闲变量{if(Usart1_IdealTime<400)//防止累加过去,造成循环{

Usart1_IdealTime++;//空闲变量累加}

}if(Usart1_IdealTime>=100)//调节这个值以适应不同的接收速率{

Usart1_TimeFlage=0;//停止空闲变量累加Usart1_IdealTime =0;//清零空闲累加变量Usart1_AT_flage =1;//接收标志位置一Usart1_Current_Cnt = Usart1_REC_Cnt;//拷贝接收的数据个数Usart1_REC_Cnt =0;//清零接收的数据个数}if(Usart3_TimeFlage ==1)//开始累加空闲变量{if(Usart3_IdealTime<400)//防止累加过去,造成循环{

Usart3_IdealTime++;//空闲变量累加}

}if(Usart3_IdealTime>=100)//调节这个值以适应不停的接收速率{

Usart3_TimeFlage=0;//停止空闲变量累加Usart3_IdealTime =0;//清零空闲累加变量Usart3_AT_flage =1;//接收标志位置一Usart3_Current_Cnt = Usart3_REC_Cnt;//拷贝接收的数据个数Usart3_REC_Cnt =0;//清零接收的数据个数}

}

}

那么主循环里---具体的处理函数,改为自己的就行

源码,,这个是用的板子的空闲中断,,,,板子的其余文件删掉便可,,,,

链接:http://pan.baidu.com/s/1c228q6c密码:pl3k

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容

  • 一、背景 最近做一个项目,需要用STM32F407来做7路串口通信,由于芯片最多只有6路,所以只能用IO口来模拟...
    Andme_6444阅读 2,611评论 0 0
  • 转眼间天亮了...... 然后就想起了一个朋友QQ的个性签名:年轻人总是要为一些自己认为有意义的事情而废寝忘食,通...
    杨奉武阅读 10,506评论 0 4
  • 整体思路ESP8266作为TCP服务器,,手机作为TCP客户端,自己使用Lua直接做到了芯片里面,省了单片机,,节...
    杨奉武阅读 5,699评论 0 5
  • 也许你并没有听说过 Realm ,这是一个面向安卓(亦面向iOS)的移动端数据库技术。和SQLite不同,它允许你...
    goolong阅读 1,072评论 2 1
  • 学习“六项精进”半年了,六项精进,看似简单,每一项都和我们日常工作生活紧密联系在一起,并没有多少高深的道理...
    徐绍刚阅读 119评论 0 0