完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
学习32,串口的使用很重要,特别是现在学的越多就觉得在很多方面通信才是主角,原子历程写的挺好,但是我看论坛里好像没怎么有这个的解析那就按自己的理解写写吧,希望能帮助到正在学习的同学。然后写在前面,初学者或者想深入学习一定要多看看参考手册。 在主函中使用以下语句实现将接收到的数据发送出去: if(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3fff; printf("rn您发送的消息为:rnrn"); for(t=0;t USART_SendData(USART1, USART_RX_BUF[t]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } 首先USART_RX_STA是什么呢?在"usart.c"里面有说明这是个接收状态标记,它既指接收状态又表明接收到数据的位数,具体使用在下文的串口中断部分中进行说明解释。 u16 USART_RX_STA=0; //接收状态标记 1 USART_RX_STA的值在USART1_IRQHandler串口接收中断函数中被改变,这里USART_RX_STA&0x8000就是判断是否已经接收到了0x0a,0x0a是LF(line feed)换行的意思,光标到达下一行,也是判断数据接收结束的标志。 提一下,中断中是以是否接收到0x0d 0x0a这两个数据,判断数据是否发送结束的。假如你发的数据没有回车(0x0d )、换行(0x0a)那么单片机是不会停止接收的(在PC中回车、换行使用回车按键就都包含了,感兴趣可以具体查查)。 程序使用数组进行数据的存储,于是这段代码也就引出一个BUG,具体描述不会描述就简单说下,嘴笨是硬伤。 比如我给单片机发送 0x01 0x02 0x03 0x04 0x05 0x06 0x0d,这时候程序还在运行继续等待接收, 再发送 0x07 0x08 0x0d 0x0a这时候接收结束,看看最后输出什么? 导致这个BUG的原因就是数组存储了信息,知道出错但没有清除,只是提一下,注意一点就行,一般使用还是可以的。 if(Res==0x0d)USART_RX_STA|=0x4000; 1 这句话呢就是判断是否接收到回车(0x0d ),接收到了回车,那么让USART_RX_STA标志位第二位为1。 if(USART_RX_STA&0x4000) { if(Res!=0x0a)USART_RX_STA=0; else USART_RX_STA|=0x8000; } 这句话呢就是判断是否接收到换行(0x0a),如果收到换行并进行判断确认收到换行符那么让USART_RX_STA标志位最高位为1。不是很懂的话,那就看看后面的那个图。至此中断就差不多说明白了,要是还有其他问题,看看下面的注释,这里我是想说怎么进行的数据处理,毕竟我觉得这一块是个难点。 void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; //中间变量,读取的数据进行保存 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //查看RXNE寄存器是否为空,以此判断是否有数据发送过来 //接收中断(接收到的数据必须是0x0d 0x0a结尾) //这里判断发送接收完成的依据就是串口数据0x0d 0x0a, //0x0d是CR(carriage return)回车的意思,光标回到最左边, //0x0a是LF(line feed)换行的意思,光标到达下一行, //但是在PC上回车和换行是在一起的就是按下回车按键 //当然可以更改程序使用其他进行判断例如使用0x2a也就是*进行结束判断 { Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据,存放到变量Res中 if((USART_RX_STA&0x8000)==0) //判断接收是否未完成 //接收完成未清除标志位,还是会不断进入到接收中断,所以使用标志进行判断, //当接收完成便不会跳入到判断,从而不执行任何指令,空等待 //使用条件判断是否已经接收完数据,这里判断接收完的依据就是收到了0x0a; //具体判断在后面 { if(USART_RX_STA&0x4000) //如果接收到了0x0d,那么再进一步执行是否接收到0x0a的判断 { if(Res!=0x0a)USART_RX_STA=0; //没有接收到0x0a那么说明,数据未正确传输或者接收错误,重新开始判断, //但是这里没有将接收到的数据进行清空,也没有退出接收中断,此程序只是从头开始执行接收判断 else USART_RX_STA|=0x8000; //接收完成了,收到了0x0a那么标志位USART_RX_STA将会变成0x8000,将不再进行数据检测与存储 } else //还没收到0X0D,说明数据还未发送结束继续进行数据的检测与存储 { if(Res==0x0d)USART_RX_STA|=0x4000; //收到了数据0x0d,标志位USART_RX_STA变成0x4000 else { //如果没有接收到数据0x0d,执行判断是否存储数组已满,已满则重新开始接收 USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; //将接收到的数据写进数组,标志位USART_RX_STA与上0X3FFF清除前两位以防止标志位与8000和4000冲突 USART_RX_STA++; //数组地址加一,向后排 if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0; //接收数据错误,超出数组大小,又开始接收向数组重新写 } } } } } 判断接收结束再判断此次接收数据的长度,USART_RX_STA也表明接收数据的位数,要想将接收到的数据全部发送出去就需要知道,一共接收到了几位然后一位一位的传出去,所以len=USART_RX_STA&0x3fff;就实现了将数据长度赋值给变量len,然后使用for循环依次将接收到的数据发送出去。这里也许会糊涂为什么是0x3fff呢?看下图能理解么? 接收到0x0d ,USART_RX_STA的值变成0x4000,又接收到0x0a,USART_RX_STA的值变成0xC000那么很容易发现数据的的前两位是作为标志位了,所以用来记录其他数据位数就只有0x3fff。 if(USART_RX_STA&0x8000) //如果在串口接收中断中接收到0x0a,数据已接收完毕 { len=USART_RX_STA&0x3fff; //得到此次接收到的数据长度,传给for循环,循环依次发出接收到的数据 printf("rn您发送的消息为:rnrn"); for(t=0;t { USART_SendData(USART1, USART_RX_BUF[t]); //向串口1发送数据,USART_SendData是库函数控制DR寄存器 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); //等待发送结束,看TC寄存器的状态 TC:发送完成 (Transmission complete) } 差不多就是这样,不懂的可以评论,有错误也请指正。一般使用串口不是这么判断使用的,具体看有没有时间,有时间整理一份。过些时候将注释的文件上传以便下载阅读。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1618 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1545 浏览 1 评论
979 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1597 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 12:52 , Processed in 0.689928 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号