×

STM32微控制器的可靠串口通信技术研究资料下载

消耗积分:2 | 格式:pdf | 大小:245.97KB | 2021-04-22

分享资料个

引言STM32F107微控制器是意法半导体推出的高性能32位以CortexM3为内核的面向工业控制的处理器。该处理器内部通过一个多层的AHB总线构架相连,其内部集成了丰富的外设,如USART、SPI、ADC等等。另外,STM32F107处理器还提供多达80个通用I/O接口,如此丰富的资源使STM32系列微控制器能够很理想地用于工业控制。本文设计出一种基于STM32F107的可靠串口通信设计方案,可以完成STM32F107处理器和PC机以及其他串口之间的可靠通信[1]。1 串口通信的实现1.1 硬件设计STM32F107处理器的通用同步异步通信单元(USART)提供 5个独立的异步串行接口,并且都能工作在中断和DMA模式下,支持LIN、智能卡协议和IRDA SIM ENDEC规范。USART的字符采用一种特殊的结构,它由起始位、数据位(8位或者9位)、停止位(1位或者2位)组成。由于STM32F107处理器输出的是TTL/CMOS电平,而计算机的标准配置串口输出为RS232电平,所以在硬件上采用MAX232进行电平转换,电路设计比较简单。如图1所示,如果在两个处理器之间进行串口通信,需要把STM32F107 的UART接口的发送端与对端串口的接收端相连,把STM32F107 的UART接口的接收端与对端串口的发送端相连[2]。1.2 软件设计和实现要实现基于STM32F107 的串口通信,首先需要对该串口的相关寄存器进行配置,比如串口的波特率、数据位长度和校验位等信息都是需要配置的。然后使能串口时钟,设置相应的I/O模式,最后进行程序设计。串口相关寄存器的配置信息如表1所列。图1 串口通信硬件电路图为了实现高效的串口数据收发,串口通信的程序设计一般采用串口的接收中断、发送中断以及FIFO缓存来实现。当串口有数据发送时,其底层的发送函数并不是真正的串口发送,而是将数据写入缓存区,缓存区按照FIFO的先入先出的结构进行组织,写入数据到FIFO后使能串口发送中断后便退出了,这相当于RAM的读写,执行速度快,实际的发送数据在串口发送中断服务程序中完成。表1 串口寄存器的配置表图2 通信协议帧当串口有数据接收时,在接收中断中使用FIFO缓存接收到的数据。当收到串口接收数据完成或者接收缓冲区已满的信息后,通知主程序数据接收完成,在主程序中进行数据处理并清理缓冲区数据,等待下一次数据接收。主程序中具体步骤如下:①配置串口中断向量表,包括配置中断的抢占优先级,响应优先级、编号和分组等内容。调用库函数NVIC_Init(&NVIC_InitStructure)。②初始化串口,包括串口时钟配置、GPIO配置、根据参数初始化并使能串口。由于 STM32F107 固件函数库提供了每一步操作的函数,所以串口的配置非常方便。最后,使能接收和发送中断,调用库函数:STM_EVAL_COMInit(COMx, &USART_InitStructure);③在主程序中等待串口接收数据完成或缓存区溢出,该信息由串口状态寄存器提供,代码为:while (1){//判断是否接收完成或缓存区溢出if (USART_Rx_Done==1) {//数据接收处理……//清空缓冲区USART_Rx_Buffer_Clear();}}④中断服务函数编写,通过判断状态寄存器USART _SR的RXNE、ORE和TXE位的状态来进行接收和发送数据[3]。代码如下:void USARTx_IRQHandler(void){//判断是否收到数据if (USARTx ->SR&(1<<5)){//接收数据USART_ReceiveData(USARTx) ;} //判断是否溢出if (USARTx ->SR&(1<<3)){//接收数据(void)USART_ReceiveData(USARTx);} //如果发送数据寄存器为空,那么左移7位if(USARTx ->SR&(1<<7)){//发送数据USART_SendBufferData();}}2 串口通信协议制定串口通信协议按照HDLC规程设计,其帧结构如图2所示。帧结构说明如下。(1) 标志所有信息传输必须以一个标志字符开始,且以同一个字符结束。从开始标志到结束标志之间构成一个完整的信息单位,称为一帧。接收端可以通过搜索标志字符来探知帧的开头和结束,以此建立帧同步。在两帧之间只需要一个这样的标记,两个相继的标记构成一个空帧,它被抛弃,而不产生FCS错误。(2) 地址域在标志之后,有一个地址域。地址域包括接收信息和发送信息的通信设备地址,即帧数据的接收者和发送者地址。地址域的宽度为16位,前8位用来表示接收者的地址,后8位用来表示发送者的地址。地址域通常在一对多或多对多的串口通信中应用。(3) 控制域在地址域之后是控制域,控制域可规定若干个命令,控制域占一个字节。接收方必须检查每个地址,包括二进制11111111(十六进制0xff),也就是“广播”地址。不可识别的地址则被抛弃。(4) 信息域跟在控制域之后的是信息域。信息域包含要传送的数据,并不是每一帧都必须传送数据,即信息域可以为0。当它为0时,这一帧主要是控制命令。(5) CRC校验紧跟在信息域之后的是4字节的帧校验,帧校验采用32位循环冗余校验码CRC。除了标志域以外,所有的信息都参加CRC计算。当数据传输时,CRC的高位在前,低位在后。帧校验序列的循环冗余码校验简称CRC(Cyclic Redundancy Check),它是利用除法及余数的原理来作错误侦测的。应用时,发送设备计算出CRC值并随数据一同发送给接收设备,接收设备对收到的数据重新计算,并与收到的CRC相比较。若两个CRC值不同,则说明数据通信出现错误。这里选用以太网的CRC32码作为帧校验产生方式。3 硬件CRC循环冗余校验由于串口通信中的数据在传输和存储过程中易受到各种信号的干扰,容易产生信号码元的变化,需要采用相关的校验方式来保证信号传输的可靠性。循环冗余校验技术主要应用于检验或核实数据传输、存储的正确性和完整性,具有检错率高、易于实现的特点,因此在工程中广泛使用。在STM32F107 中内置了CRC计算单元的硬件组件,所以不需要额外设计任何硬件电路,而且计算速度较快。内置CRC计算单元是根据固定的生成多项式得到任一32位全字的CRC计算结果。CRC计算单元可以在程序运行时计算出软件的标识,之后与在连接时生成的参考标识比较,然后存放在指定的存储器空间[4]。STM32F107 内置的CRC计算单元操作方便,首先复位CRC模块,即CRC->CR =0x01。然后,把要计算的数据每32位分为一组,写入到CRC_DR寄存器中,写完数据后就可以从CRC_DR寄存器读出数据了。虽然数据的读写都是在CRC_DR寄存器中进行,但是实际上访问的是不同的物理寄存器。STM32F107 内置CRC计算单元框图如图3所示。结语随着32位以CortexM3为内核的STM32F107 微处理器在工业控制中的广泛应用,串口作为一种微控制器必不可少的通信接口,应用也比较广泛。针对串口在应用过程中容易出现的误码问题,本文设计出一种基于STM32F107 的可靠串口通信方案,利用STM32F107 内置的CRC计算单元产生校验数据来保证通信的可靠性。该方案可以完成STM32F107 处理器与计算机之间以及其他微控制器串口之间的可靠通信。(mbbeetchina)

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(1)
发评论
江南皖人 2021-08-06
0 回复 举报
很好的资料,不错 收起回复

下载排行榜

全部1条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'STM32微控制器的可靠串口通信技术研究资料下载',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);