你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

MK电调串口报文分析及采用STM32实现——想搞电调的小伙伴...  

[复制链接]
shiyongzhu 发布时间:2015-2-3 23:21
一、关于串口
串口通信是我们平时调试中经常使用到的一种调试方法,其连接简易,拔插相对方便,而且使用过程中上位机不需要安装驱动程序(除非使用USB转串口工具),因而在电调的调试过程,若能实时的通过串口向计算机发送电调状态信息,将会十分的有助于电调的开发工作。但是串口的缺点是每次只能发送一个字节的数据,对于需要的发送一串数据的情况,一般采用循环发送方式(如printf),浪费了处理器的时间,而且对于一些复杂的数据如float、int数据则还需转化成字符型才能进行发送。如何实现一个既能实现不占用太多处理器时间,而且可以发送一些复杂数据类型的串口变得十分必要。MK电调这方面做的很好值得我们学习一番。
二、MK电调调试串口功能实现
首先MK电调中定义了一个用于输出调试信息的数据类型str_DebugOut
struct str_DebugOut
{
unsigned char Digital[2];
unsigned int Analog[8];    // Debugwerte
};
接着定义了一个基于该类型的变量DebugOut
主程序中调试输出部分程序片段如下,该段程序在while下循环的运行。
………………
if(!UebertragungAbgeschlossen) SendUart();
else DatenUebertragung();
………………
UebertragungAbgeschlossen为数据发送完成的标志。0表示一组报文发送未完成,1表示完成一组报文发送。
首先我们假定一组报文已经发送完成
则调用函数voidDatenUebertragung(void) ,进行数据编码和定时发送设定工作。
void DatenUebertragung(void)  
{
if((CheckDelay(Debug_Timer) &&UebertragungAbgeschlossen))   
   {
             SendOutData('D',MeineSlaveAdresse,(unsignedchar *) &DebugOut,sizeof(DebugOut));
          Debug_Timer = SetDelay(50);   // Sendeintervall
            }
}
而函数DatenUebertragung调用了SendOutData(unsigned charcmd,unsigned char modul, unsigned char *snd, unsigned char len)函数,该函数将调试信息进行数据的重新编码,并且加入的CRC校验位,进一步提高了数据的可靠性。
SendOutData函数的具体定义如下:
voidSendOutData(unsigned char cmd,unsigned char modul, unsigned char *snd, unsignedchar len)
{
unsigned int pt = 0;
unsigned char a,b,c;
unsigned char ptr = 0;

- N6 b8 X8 s* ?) G) j- ?
SendeBuffer[pt++] = '#';               // Startzeichen
SendeBuffer[pt++] = modul;             // Adresse (a=0; b=1,...)
SendeBuffer[pt++] = cmd;                    // Commando
' T8 H$ Z3 [% A! [& Y
while(len)
  {
   if(len) { a = snd[ptr++]; len--;} else a =0;
   if(len) { b = snd[ptr++]; len--;} else b =0;
   if(len) { c = snd[ptr++]; len--;} else c =0;
   SendeBuffer[pt++] = '=' + (a >> 2);
   SendeBuffer[pt++] = '=' + (((a & 0x03)<< 4) | ((b & 0xf0) >> 4));
   SendeBuffer[pt++] = '=' + (((b & 0x0f)<< 2) | ((c & 0xc0) >> 6));
   SendeBuffer[pt++] = '=' + ( c & 0x3f);
  }
AddCRC(pt);
}
AddCRC函数如下:
voidAddCRC(unsigned int wieviele)
{
unsigned int tmpCRC = 0,i;
for(i = 0; i < wieviele;i++)
  {
   tmpCRC += SendeBuffer;
  }
   tmpCRC %= 4096;
   SendeBuffer[i++] = '=' + tmpCRC / 64;
   SendeBuffer[i++] = '=' + tmpCRC % 64;
   SendeBuffer[i++] = '\r';
  UebertragungAbgeschlossen = 0;
  UDR = SendeBuffer[0];
}
上述函数中SendeBuffer为串口发送的缓存区,很明显发送的报文包头为'#',随后是modul,其次是cmd,后面跟着的是调试信息的重新编码数据,然后CRC校验码,最后是结束符'\r'。该部分的数据编码,则是MK电调串口通信的精华部分。
       MK电调进行数据编码的一个重要目的就是要能够在接受数据端能够识别出报文起始'#'和结束符'\r',因此在报文的中间必须不能够出现与这两个字符相同的字符。以下列出使用到的几个关键ASCII码。
#  —  35(十进制)    0x23(十六进制)
\r  —  13(十进制)    0x0D(十六进制)
=  — 61(十进制)    0x3D(十六进制)
从上述的ASCII码值,只要数据区的每个字节值>35或者<13时即可识别到报文的头和尾,很明显大于35的数据范围比较广,所以将数据编码到大于35的ASCII码的值比较方便。MK电调采用此种方法,将原来的数据由三个字节扩充为四个字节,并将各个字节加上‘=’(0x3D),从而使得扩充后的字节均大于‘#’。编码后的数据区数据将全部大于’#’、‘\r’,从而从接收得到的报文中可以检测出报文头和尾,是不是设计的非常巧妙啊,德国人果然很严谨啊!!
数据编码完成了,下面就是数据发送了,如果采用一股脑的发送方式(如printf()等),将会浪费处理器不少的时间,软件的实时性得不到保证,那怎么办年。首先设定一个定时输出的调试信息的定时器Debug_Timer,定时器时间到后则启动函数DatenUebertragung()进行数据编码,把数据准备好,然后在主程序中持续的查询数据有没有发送完成的标志UebertragungAbgeschlossen(前文提到了该标志),若发送未完成则进行发送运行函数SendUart,否则运行DatenUebertragung()进行数据编码,
进入SendUart函数也不一定就可以立马发送数据,因此进入该函数后,首先查询下串口发送标志,串口忙则不发送直接返回,串口闲的话就再发送一个字节了,全部数据包发送完成后将发送完成标志置位。
void SendUart(void)
{
static unsigned int ptr = 0;
unsigned char tmp_tx;
if(!(UCSRA & 0x40)) return;
if(!UebertragungAbgeschlossen)  
  {
  ptr++;                    // die[0] wurde schon gesendet
  tmp_tx = SendeBuffer[ptr];  
  if((tmp_tx == '\r') || (ptr == MAX_SENDE_BUFF))
    {
    ptr = 0;
    UebertragungAbgeschlossen = 1;
    }
  USR |= (1<TXC);
  UDR = tmp_tx;
  }
else ptr = 0;
}
采用这种串口编码方式是不是既能保证不占用处理器的时间,又能够发送复杂的数据类型啊。
三、基于STM32的MK电调调试串口功能实现
分析完了MK电调后,考虑下如何在STM32 中实现吧,首先数据编码这块的可以直接采用MK电调的方法,而数据发送部分在STM32 中可以做的更简化些,使用串口发送DMA功能进行实现,将串口DMA的发送缓存器指向数据区,当编码完成后,使能串口发送DMA功能,不需要处理器干涉数据将进行发送。附件里提供MK电调的源码和采用STM32实现该功能的源代码。
BLDC-DIY.rar (4.72 MB, 下载次数: 369)
收藏 4 评论26 发布时间:2015-2-3 23:21

举报

26个回答
shiyongzhu 回答时间:2015-2-5 16:31:56
湛无双 发表于 2015-2-4 23:41( V. H9 l. C, s3 Y7 A$ g7 t
楼主,这个不简单呀!给赞一个,必须要留名。
! P: E9 }6 u  B, v9 x
谢谢顶帖!
shiyongzhu 回答时间:2015-2-9 12:27:35
759611 发表于 2015-2-8 11:55
& w. N% G- d1 v3 T6 }不错,收藏了

0 B  y! U: e6 y+ V谢谢,欢迎交流。
elecfanss 回答时间:2015-2-7 18:19:41
CRC部分是否可以使用STM32中的CRC功能来实现呢?
无位置 回答时间:2015-2-4 09:26:20
顶一下楼主!!!
shiyongzhu 回答时间:2015-2-4 18:17:33
无位置 发表于 2015-2-4 09:261 O+ X3 _+ ^$ l
顶一下楼主!!!

/ w* n$ |; [) R+ M; z谢谢顶贴!!
湛无双 回答时间:2015-2-4 23:41:40
楼主,这个不简单呀!给赞一个,必须要留名。
sdkdwyb-321669 回答时间:2015-2-5 00:04:57
mark一下,明年好好弄电调
wz002 回答时间:2015-2-6 00:07:51
赞一个
sheepnorth 回答时间:2015-2-6 09:37:29
收着,留着搞四轴时用。
MouseCat 回答时间:2015-2-8 11:41:00
收藏备用
759611 回答时间:2015-2-8 11:55:27
不错,收藏了
黑溱郎 回答时间:2015-2-9 10:57:46
记号——MK电调串口报文分析及采用STM32实现
dragonfly1234 回答时间:2015-2-9 21:38:43
看着还行~或许以后用得着~
lkl0305 回答时间:2015-2-9 21:43:58
收藏了
12下一页

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版