精华内容
下载资源
问答
  • 1 importos2 importtime3 importsys, traceback4 from serial.serialutil importSerialException5 from serial importSerial67 importstruct8 importbinascii91011 classArduino:12 def __init__(self, port="/d...

    1 importos2 importtime3 importsys, traceback4 from serial.serialutil importSerialException5 from serial importSerial6

    7 importstruct8 importbinascii9

    10

    11 classArduino:12 def __init__(self, port="/dev/ttyUSB0", baudrate=115200, timeout=0.5):13

    14 self.port =port15 self.baudrate =baudrate16 self.timeout =timeout17 self.encoder_count =018 self.writeTimeout =timeout19 self.interCharTimeout = timeout / 30.20

    21 self.WAITING_FF =022 self.WAITING_AA = 1

    23 self.RECEIVE_LEN = 2

    24 self.RECEIVE_PACKAGE = 3

    25 self.RECEIVE_CHECK = 4

    26 self.HEADER0 = 0xff

    27 self.HEADER1 = 0xaa

    28 self.REC_CMD = 5

    29 self.count =030 self.data1 =031 self.data2 =032 self.error_flag =033 self.SUCCESS =034 self.FAIL = -1

    35

    36 self.receive_state_ =self.WAITING_FF37 self.receive_check_sum_ =038 self.payload_command = ‘‘

    39 self.payload_ack = ‘‘

    40 self.payload_args = ‘‘

    41 self.payload_len =042 self.byte_count_ =043 self.receive_message_length_ =044

    45 self.mutex =threading.Thread.allocate_lock()46

    47 #An array to cache analog sensor readings

    48 self.analog_sensor_cache = [None] *self.N_ANALOG_PORTS49

    50 #An array to cache digital sensor readings

    51 self.digital_sensor_cache = [None] *self.N_DIGITAL_PORTS52

    53 defconnect(self):54 try:55 print "Connecting to Arduino on port", self.port, "..."

    56 self.port = Serial(port=self.port, baudrate=self.baudrate, timeout=self.timeout, writeTimeout=self.writeTimeout)57 #The next line is necessary to give the firmware time to wake up.

    58 time.sleep(1)59 state_, val =self.get_baud()60 if val !=self.baudrate:61 time.sleep(1)62 state_, val =self.get_baud()63 if val !=self.baudrate:64 raiseSerialException65 print "Connected at", self.baudrate66 print "Arduino is ready."

    67

    68 exceptSerialException:69 print "Serial Exception:"

    70 printsys.exc_info()71 print "Traceback follows:"

    72 traceback.print_exc(file=sys.stdout)73 print "Cannot connect to Arduino!"

    74 os._exit(1)75

    76 defopen(self):77 self.port.open()78

    79 defclose(self):80 self.port.close()81

    82 defsend(self, cmd):83 self.port.write(cmd)84

    85 defreceiveFiniteStates(self, rx_data):86 if self.receive_state_ ==self.WAITING_FF:87 #print str(binascii.b2a_hex(rx_data))

    88 if rx_data == ‘\xff‘:89 self.receive_state_ =self.WAITING_AA90 self.receive_check_sum_ =091 self.receive_message_length_ =092 self.byte_count_=093 self.payload_ack = ‘‘

    94 self.payload_args = ‘‘

    95 self.payload_len =096 self.count =097

    98 elif self.receive_state_ ==self.WAITING_AA :99 if rx_data == ‘\xaa‘:100 self.receive_state_ =self.REC_CMD101 else:102 self.receive_state_ =self.WAITING_FF103 elif self.receive_state_ ==self.REC_CMD:104 self.count+=1

    105 if self.count == 1:106 self.data1,=struct.unpack("B",rx_data)107 elif self.count == 2:108 self.data2,=struct.unpack("B",rx_data)109 self.receive_state_ =self.RECEIVE_LEN110 if self.error_flag == 0 and self.data1 !=0:111 self.error_flag = 1

    112 if self.data2 != 0 and self.error_flag ==0:113 self.error_flag = 1

    114 elif self.receive_state_ ==self.RECEIVE_LEN:115 self.receive_message_length_, = struct.unpack("B",rx_data)116 self.receive_state_ =self.RECEIVE_PACKAGE117 elif self.receive_state_ ==self.RECEIVE_PACKAGE:118 if self.byte_count_==0:119 self.payload_ack =rx_data120 else:121 self.payload_args +=rx_data122 self.byte_count_ +=1

    123 #print "byte:"+str(byte_count_) +","+ "rece_len:"+str(receive_message_length_)

    124 if self.byte_count_ >=self.receive_message_length_:125 self.receive_state_ =self.RECEIVE_CHECK126

    127 elif self.receive_state_ ==self.RECEIVE_CHECK:128 #if(rx_data == (unsigned char)receive_check_sum_)

    129 if 1:130 self.receive_state_ =self.WAITING_FF131 #print str(binascii.b2a_hex(value))

    132 #left, right, = struct.unpack(‘hh‘, value)

    133 #print "left:"+str(left)+", right:"+str(right)

    134 return 1

    135 else:136 self.receive_state_ =self.WAITING_FF137 else:138 self.receive_state_ =self.WAITING_FF;139 return0140

    141 def recv(self, timeout=0.5):142 timeout =min(timeout, self.timeout)143 ‘‘‘This command should not be used on its own: it is called by the execute commands144 below in a thread safe manner. Note: we use read() instead of readline() since145 readline() tends to return garbage characters from the Arduino146 ‘‘‘

    147 c = ‘‘

    148 value = ‘‘

    149 attempts =0150 c = self.port.read(1)151 #print str(binascii.b2a_hex(c))

    152 while self.receiveFiniteStates(c) != 1:153 c = self.port.read(1)154 #print str(binascii.b2a_hex(c))

    155 attempts += 1

    156 if attempts * self.interCharTimeout >timeout:157 return0158 return 1

    159

    160 defrecv_ack(self):161 ack =self.recv(self.timeout)162 return ack == ‘OK‘

    163

    164 defexecute(self, cmd):165 self.mutex.acquire()166

    167 try:168 self.port.flushInput()169 except:170 pass

    171

    172 ntries = 1

    173 attempts =0174

    175 try:176 self.port.write(cmd)177 res =self.recv(self.timeout)178 while attempts < ntries and res !=1:179 try:180 self.port.flushInput()181 self.port.write(cmd)182 res =self.recv(self.timeout)183 except:184 print "Exception executing command:" +str(binascii.b2a_hex(cmd))185 attempts += 1

    186 except:187 self.mutex.release()188 print "Exception executing command:" +str(binascii.b2a_hex(cmd))189 return0190

    191 self.mutex.release()192 return 1

    193

    194 defget_baud(self):195 ‘‘‘Get the current baud rate on the serial port.196 ‘‘‘

    197 cmd_str=struct.pack("4B", self.HEADER0, self.HEADER1, 0x01, 0x00) + struct.pack("B", 0x01)198 if (self.execute(cmd_str))==1 and self.payload_ack == ‘\x00‘:199 val, = struct.unpack(‘I‘, self.payload_args)200 returnself.SUCCESS, val201 else:202 returnself.FAIL, 0203

    204 defget_check_sum(self,list):205 list_len =len(list)206 cs =0207 for i inrange(list_len):208 #print i, list[i]

    209 cs +=list[i]210 cs=cs%255

    211 returncs212

    213 defstop(self):214 ‘‘‘Stop both motors.215 ‘‘‘

    216 self.drive(0, 0)

    展开全文
  • 学习笔记:openmv与STM32串口传输数据解析程序

    千次阅读 多人点赞 2019-10-19 21:37:08
    学习笔记:openmv与STM32串口传输数据解析程序 学习初衷 大四毕业设计需要用到openmv与STM32之间的数据传输 由于之前没有学过Python,所以在openmvide编写程序时遇到很多问题。但是不得不说Python是真的好用...

    学习笔记:openmv与STM32串口传输数据的解析程序

    学习初衷

    大四毕业设计需要用到openmv与STM32之间的数据传输
    由于之前没有学过Python,所以在openmvide编写程序时遇到很多问题。但是不得不说Python是真的好用啊!开始时把这个问题想的很简单,因为之前也做过单片机之间的数据传输解析,可能是自身实力太差的原因,在借鉴其他博主的文章之后搞了两天才算是有些眉目。第一次写csdn的博客,有什么没表述清楚的,也请见谅,希望可以给到你一些帮助,欢迎大家一起学习和交流。

    Openmv代码部分

    这是一个识别最大圆并获取最大圆与中心坐标的代码
    最初的方案是采用字符的方式从openmv发送给STM32,但经过多次试验后,解析不成功,而且很容易掉帧
    但是在python中我没有学过怎么用串口发送16进制数。
    在查阅资料后发现bytearray()这个函数在openmv中能直接输出一个16进制字节数组
    然后通过串口可以发送。以下是openmv ide中的代码。

    
    import sensor, image, time
    from pyb import UART
    import json
    
    red_threshold  = (87, 21, 27, 93, -5, 92)
    sensor.reset() # Initialize the camera sensor.
    sensor.set_pixformat(sensor.RGB565) # use RGB565.
    sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
    sensor.skip_frames(10) # Let new settings take affect.
    sensor.set_auto_whitebal(False) # turn this off.
    clock = time.clock() # Tracks FPS.
    
    uart = UART(3, 115200)
    uart.init(115200, bits=8, parity=None, stop=1)  #8位数据位,无校验位,1位停止位
    
    def find_max(blobs):
        max_size=0
        for blob in blobs:
            if blob[2]*blob[3] > max_size:
                max_blob=blob
                max_size = blob[2]*blob[3]
        return max_blob
    while(True):
        clock.tick() # Track elapsed milliseconds between snapshots().
        img = sensor.snapshot() # Take a picture and return the image.
    
        blobs = img.find_blobs([red_threshold])
        if blobs:
    
            max_blob = find_max(blobs)
            img.draw_cross(max_blob.cx(),max_blob.cy())
            img.draw_circle(max_blob.cx(),max_blob.cy(),max_blob.cx()-max_blob.x(), color = (255, 255, 255))
            X =int(max_blob.cx()-img.width()/2)
            Y =int(max_blob.cy()-img.height()/2)
            
          #  FH = bytearray([0xb3,0xb3])
          #  uart.write(FH)     #打印帧头
    
            data = bytearray([0xb3,0xb3,X,Y,0x5b])
            uart.write(data)    #打印XY轴的偏移坐标
            
     
            print("X轴偏移坐标 : ",X)
            print("Y轴偏移坐标 : ",Y)
    
    
            print("帧率 : ",clock.fps())
    
    

    STM32代码部分

    解决的openmv发送的问题,现在就要解决如何能稳定无误的接收到数据,并解析
    我采用了比较通用的(帧头、帧头、数据+、帧尾)当STM32这是一帧数据解析到这样一帧数据时,就得到了我们想要的数据。以下是STM32中的代码
    这个是中断处理的函数

    void USART1_IRQHandler(void)                	//串口1中断服务程序
    	{
    	u8 com_data;
    #if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    	OSIntEnter();    
    #endif
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    		{
    			USART_ClearFlag(USART1,USART_FLAG_RXNE);
          com_data = USART1->DR;
    			Openmv_Receive_Data(com_data);     //openmv数据处理函数
    			Openmv_Data();		                 //openmv数据处理函数		
     		
         } 
    #if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    	OSIntExit();  											 
    #endif
    } 
    

    数据解析部分的程序

    #include "openmv.h"
    int openmv[5];//stm32接收数据数组
    int8_t OpenMV_X;          /*OPENMV X 轴反馈坐标*/
    int8_t OpenMV_Y;          /*OPENMV X 轴反馈坐标*/
    
    
    int i=0;
    
    void Openmv_Receive_Data(int16_t data)//接收Openmv传过来的数据
    {
    	static u8 state = 0;
    	if(state==0&&data==0xb3)
    	{
    		state=1;
    		openmv[0]=data;
    	}
    	else if(state==1&&data==0xb3)
    	{
    		state=2;
    		openmv[1]=data;
    	}
    	else if(state==2)
    	{
    		state=3;
    		openmv[2]=data;
    	}
    	else if(state==3)
    	{
    		state = 4;
    		openmv[3]=data;
    	}
    
    	else if(state==4)		//检测是否接受到结束标志
    	{
            if(data == 0x5B)
            {
                state = 0;
                openmv[4]=data;
                Openmv_Data();
            }
            else if(data != 0x5B)
            {
                state = 0;
                for(i=0;i<5;i++)
                {
                    openmv[i]=0x00;
                }           
            }
    	}    
    	else
    		{
    			state = 0;
                for(i=0;i<5;i++)
                {
                    openmv[i]=0x00;
                }
    		}
    }
    
    void Openmv_Data(void)
    {
        OpenMV_X=openmv[2];
        OpenMV_Y=openmv[3];
    
    }
    
    
    

    需要注意这里的帧头和帧尾需要和OPENMV设置的帧头帧尾匹配。

    主函数部分采用串口直接打印
    经过多次测试把串口打印放在每5ms中断的定时器服务函数中是会出现掉帧的现象,而且数据解析也失效了,这点问题还不知道如何解决。

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"
    #include "holder.h" 
    #include "oled.h"
    #include "mpu6050.h"
    #include "control.h"
    #include "HMI.h"
    #include "usart2.h"	
    #include "openmv.h"
    /*全局变量*/
    
    
    
     int main(void)
     {		
     	u16 t;  
    	u16 len;	
    	u16 times=0;
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    
    // 	
    //	IIC_Init();
    //  delay_ms(500);
    //	MPU6050_initialize();         /*MPU6050初始化*/	
    //  DMP_Init();
    	 
    	LED_Init();			              /*LED端口初始化*/
    	KEY_Init();                   /*初始化与按键连接的硬件接口*/
     
      uart_init(115200);	          /*opemv串口接收*/ 
    	uart3_init(9600);             /*串口屏*/
    	uart2_init(9600);            /*串口发送printf*/
    	 
    	TIM2_Getsample_Int(4999,71);	/*5ms定时中断*/
      PWM_Mode_Config();  	        /* 舵机初始化*/ 
    	OLED_Init();                  /*OLED初始化*/
    	OLED_Clear();                 /*主界面*/ 
     	while(1)
    	{
    		
       	 printf("\n\r X偏移= %.d Y偏移= %.d \n\r",OpenMV_X ,OpenMV_Y);   /*X轴左负右正  */
    
    	}	
    }
    
    
    
    

    运行效果图片

    openmv端数据
    这个是通过串口打印助手所得到的数据
    可以看出两端的数据还是很匹配的。
    调试的时候要把串口助手的波特率调节到与STM32串口的所匹配值
    经过多次测试后可以在STM32端稳定得出所要要数据,而且帧速率也不错

    展开全文
  • 1、最近有个想做一个传感器数据实时显示的上位机,常规的数据打印太频繁了,无法直观的看出数据的变化。...最大的问题点在于对bytes型数据的拼接:之前的串口解析的代码是在python 2.7平台上实现的, 切换到pyt...

    1、最近有个想做一个传感器数据实时显示的上位机,常规的数据打印太频繁了,无法直观的看出数据的变化。

    python下的上位机实现起来简单一点,网上找了一些python界面Tkinter相关资料和python串口的demo.测试实现了简单的数据显示。

     

    Mark 一下问题点:

    最大的问题点在于对bytes型数据的拼接:之前的串口解析的代码是在python 2.7平台上实现的,

    切换到python3.0之后,测试失踪无法通过。幸而找到了大神相助。

    python 2.7code:

      1 import os
      2 import time
      3 import sys, traceback
      4 from serial.serialutil import SerialException
      5 from serial import Serial
      6 
      7 import struct
      8 import binascii
      9 
     10 
     11 class Arduino:
     12     def __init__(self, port="/dev/ttyUSB0", baudrate=115200, timeout=0.5):
     13         
     14         self.port = port
     15         self.baudrate = baudrate
     16         self.timeout = timeout
     17         self.encoder_count = 0
     18         self.writeTimeout = timeout
     19         self.interCharTimeout = timeout / 30.
     20 
     21         self.WAITING_FF = 0
     22         self.WAITING_AA = 1
     23         self.RECEIVE_LEN = 2
     24         self.RECEIVE_PACKAGE = 3
     25         self.RECEIVE_CHECK = 4
     26         self.HEADER0 = 0xff
     27         self.HEADER1 = 0xaa
     28         self.REC_CMD = 5
     29         self.count   = 0
     30         self.data1   = 0
     31         self.data2   = 0
     32         self.error_flag = 0
     33         self.SUCCESS = 0
     34         self.FAIL = -1
     35 
     36         self.receive_state_ = self.WAITING_FF
     37         self.receive_check_sum_ = 0
     38         self.payload_command = ''
     39         self.payload_ack = ''
     40         self.payload_args = ''
     41         self.payload_len = 0
     42         self.byte_count_ = 0
     43         self.receive_message_length_ = 0
     44     
     45         self.mutex = threading.Thread.allocate_lock()
     46             
     47         # An array to cache analog sensor readings
     48         self.analog_sensor_cache = [None] * self.N_ANALOG_PORTS
     49         
     50         # An array to cache digital sensor readings
     51         self.digital_sensor_cache = [None] * self.N_DIGITAL_PORTS
     52     
     53     def connect(self):
     54         try:
     55             print "Connecting to Arduino on port", self.port, "..."
     56             self.port = Serial(port=self.port, baudrate=self.baudrate, timeout=self.timeout, writeTimeout=self.writeTimeout)
     57             # The next line is necessary to give the firmware time to wake up.
     58             time.sleep(1)
     59             state_, val = self.get_baud()
     60             if val != self.baudrate:
     61                 time.sleep(1)
     62                 state_, val  = self.get_baud()   
     63                 if val != self.baudrate:
     64                     raise SerialException
     65             print "Connected at", self.baudrate
     66             print "Arduino is ready."
     67 
     68         except SerialException:
     69             print "Serial Exception:"
     70             print sys.exc_info()
     71             print "Traceback follows:"
     72             traceback.print_exc(file=sys.stdout)
     73             print "Cannot connect to Arduino!"
     74             os._exit(1)
     75 
     76     def open(self): 
     77         self.port.open()
     78 
     79     def close(self): 
     80         self.port.close() 
     81     
     82     def send(self, cmd):
     83         self.port.write(cmd)
     84 
     85     def receiveFiniteStates(self, rx_data):
     86         if self.receive_state_ == self.WAITING_FF:
     87             #print str(binascii.b2a_hex(rx_data))
     88             if rx_data == '\xff':
     89                 self.receive_state_ = self.WAITING_AA
     90                 self.receive_check_sum_ =0
     91                 self.receive_message_length_ = 0
     92                 self.byte_count_=0
     93                 self.payload_ack = ''
     94                 self.payload_args = ''
     95                 self.payload_len = 0
     96                 self.count = 0
     97 
     98         elif self.receive_state_ == self.WAITING_AA :
     99              if rx_data == '\xaa':
    100                  self.receive_state_ = self.REC_CMD
    101              else:
    102                  self.receive_state_ = self.WAITING_FF
    103         elif self.receive_state_ == self.REC_CMD:
    104              self.count+=1
    105              if self.count == 1:
    106                 self.data1,=struct.unpack("B",rx_data)
    107              elif self.count == 2:
    108                   self.data2,=struct.unpack("B",rx_data)
    109                   self.receive_state_ = self.RECEIVE_LEN
    110                   if self.error_flag == 0 and self.data1 != 0:
    111                      self.error_flag = 1
    112                   if self.data2 != 0 and self.error_flag == 0:
    113                      self.error_flag = 1   
    114         elif self.receive_state_ == self.RECEIVE_LEN:
    115              self.receive_message_length_, = struct.unpack("B",rx_data)
    116              self.receive_state_ = self.RECEIVE_PACKAGE
    117         elif self.receive_state_ == self.RECEIVE_PACKAGE:
    118              if self.byte_count_==0:
    119                  self.payload_ack = rx_data
    120              else:
    121                  self.payload_args += rx_data
    122              self.byte_count_ +=1
    123              #print "byte:"+str(byte_count_) +","+ "rece_len:"+str(receive_message_length_)
    124              if self.byte_count_ >= self.receive_message_length_:
    125                  self.receive_state_ = self.RECEIVE_CHECK
    126 
    127         elif self.receive_state_ == self.RECEIVE_CHECK:
    128             #if(rx_data == (unsigned char)receive_check_sum_)
    129             if 1:
    130                 self.receive_state_ = self.WAITING_FF
    131                 #print str(binascii.b2a_hex(value))
    132                 #left, right, = struct.unpack('hh', value)
    133                 #print "left:"+str(left)+", right:"+str(right)
    134                 return 1 
    135             else:
    136                 self.receive_state_ = self.WAITING_FF
    137         else:
    138             self.receive_state_ = self.WAITING_FF;
    139         return 0
    140 
    141     def recv(self, timeout=0.5):
    142         timeout = min(timeout, self.timeout)
    143         ''' This command should not be used on its own: it is called by the execute commands   
    144             below in a thread safe manner.  Note: we use read() instead of readline() since
    145             readline() tends to return garbage characters from the Arduino
    146         '''
    147         c = ''
    148         value = ''
    149         attempts = 0
    150         c = self.port.read(1)
    151         #print str(binascii.b2a_hex(c))
    152         while self.receiveFiniteStates(c) != 1:
    153             c = self.port.read(1)
    154             #print str(binascii.b2a_hex(c))
    155             attempts += 1
    156             if attempts * self.interCharTimeout > timeout:
    157                 return 0
    158         return 1
    159             
    160     def recv_ack(self):
    161         ack = self.recv(self.timeout)
    162         return ack == 'OK'
    163 
    164     def execute(self, cmd):
    165         self.mutex.acquire()
    166         
    167         try:
    168             self.port.flushInput()
    169         except:
    170             pass
    171         
    172         ntries = 1
    173         attempts = 0
    174         
    175         try:
    176             self.port.write(cmd)
    177             res = self.recv(self.timeout)
    178             while attempts < ntries and res !=1 :
    179                 try:
    180                     self.port.flushInput()
    181                     self.port.write(cmd)
    182                     res = self.recv(self.timeout)
    183                 except:
    184                     print "Exception executing command: " + str(binascii.b2a_hex(cmd))
    185                 attempts += 1
    186         except:
    187             self.mutex.release()
    188             print "Exception executing command: " + str(binascii.b2a_hex(cmd))
    189             return 0
    190         
    191         self.mutex.release()
    192         return 1
    193 
    194     def get_baud(self):
    195         ''' Get the current baud rate on the serial port.
    196         '''
    197         cmd_str=struct.pack("4B", self.HEADER0, self.HEADER1, 0x01, 0x00) + struct.pack("B", 0x01)
    198         if (self.execute(cmd_str))==1 and self.payload_ack == '\x00':
    199            val, = struct.unpack('I', self.payload_args)
    200            return  self.SUCCESS, val 
    201         else:
    202            return self.FAIL, 0
    203 
    204     def get_check_sum(self,list):
    205         list_len = len(list)
    206         cs = 0
    207         for i in range(list_len):
    208             #print i, list[i]
    209             cs += list[i]
    210         cs=cs%255
    211         return cs
    212         
    213     def stop(self):
    214         ''' Stop both motors.
    215         '''
    216         self.drive(0, 0)
    View Code

    在python 3.6 version 中就该修改部分代码:

     问题在于bytes类型的拼接:

    以下的拼接是正确的:

    bytes('','ascii')+bytes([1,2,3,4,5,6,7,8,9])
    bytes('','ascii')+bytes([1,2,3,4,5,6,7,8,9])+bytes([1,2,3,4,5,6,7,8,9])

    也即是:bytes类型的拼接的初始变量要声明为:bytes('','ascii')

    如果声明为其它类型:比如字符串,执行时会直接报错。

    即:python2.7代码块中:40行以及94行的声明:

    (1)将:40行和94行的
    self.payload_args = ''
    改为:
    self.payload_args = bytes('','ascii')
    (2)将:121行赋值命令:
    self.payload_args += rx_data
    修改为:
    self.payload_args +=  bytes(rx_data)
    View Code

     源码已上传到github:链接

    目前单纯实现了串口数据的查询:

     

    转载于:https://www.cnblogs.com/sshbit/p/10283185.html

    展开全文
  • 那么问题来了,现在基于stm32的Hal库把串口接收函数进行了封装,不管是非中断模式,中断模式,还是dma模式都是接收固定数量byte的数据。但是在协议处理的过程中单片机很多时候是不知道模块发过来的数据是有多少byte...

    在做项目中,stm32的串口应用常用来作为单片机和模块之间的通信。比如单片机和gsm模块通信,单片机和gps模块的通信。那么和这些模块就用到了串口的协议解析。那么问题来了,现在基于stm32的Hal库把串口接收函数进行了封装,不管是非中断模式,中断模式,还是dma模式都是接收固定数量byte的数据。但是在协议处理的过程中单片机很多时候是不知道模块发过来的数据是有多少byte的。

    我之前大部分做的时候是用中断来一个数据接收一个数据放在缓冲区,然后过一个时间片段进行分析接收到的数据。但是这种模式效率低下,还可能有丢数据的风险。最近在调试一个串口协议程序,看stm参考手册发现一个以前没有去关注过的空闲中断,觉得这个可以大大的派上了用场。随即在百度上进行了搜索,原来已经有很多小伙伴这样用过。但是在网上的资料往往都是千篇一律,一篇文章被转过来转过去。基本上都是空闲中断加DMA的方式来操作。

    我后来自己实践了,不需要dma,只用空闲中段加接收完成中段就可以完成接收一帧不定长的数据。

    我试验的平台是stm32F407,其他stm32型号都类似。基于hal库的封装还是很统一的。使用stm32cubemx进行配置。串口配置很简单,如下:

    打开串口

    配置串口参数:

    打开串口中断:

    其他配置的我就不啰嗦了,然后生成mdk工程。在mdk中我们就重点看下stm32Fxxx_it.c文件中关于串口中断这块代码

    void USART1_IRQHandler(void)

    {

    /* USER CODE BEGIN USART1_IRQn 0 */

    /* USER CODE END USART1_IRQn 0 */

    HAL_UART_IRQHandler(&huart1);

    /* USER CODE BEGIN USART1_IRQn 1 */

    /* USER CODE END USART1_IRQn 1 */

    }

    在中断服务函数里面调用了HAL_UART_IRQHandler(&huart1),这个也是st hal库封装的基础。而我要做的就是不再用st对中断的封装而自己去处理。于是乎我进行了改装,如下:

    void USART1_IRQHandler(void)

    {

    /* USER CODE BEGIN USART1_IRQn 0 */

    user_Uart1Handler();

    /* USER CODE END USART1_IRQn 0 */

    /* USER CODE BEGIN USART1_IRQn 1 */

    /* USER CODE END USART1_IRQn 1 */

    }

    我把官方的中断函数换成了自己的user_Uart1Handler() 。之后串口的中断都有我这个函数来处理了。具体内容如下:

    void user_Uart1Handler()

    {

    if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))

    {

    if(uart1RxState==UART_RX_STATE_READY) //接收到一帧中的第一个字节

    {

    uart1RxState=UART_RX_STATE_START;

    __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //打开空闲中断

    uart1RxCounter=0; //计数清零

    uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);

    uart1RxCounter++;

    }

    else if(uart1RxState==UART_RX_STATE_START)

    {

    uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);

    uart1RxCounter++;

    }

    __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);

    }

    if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)) //进入空闲中断

    {

    __HAL_UART_DISABLE_IT(&huart1,UART_IT_IDLE); //关了空闲中断

    __HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE); //关了接收完成中断

    uart1RxState=UART_RX_STATE_DEAL; //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开

    }

    }

    除了这里的改造外还需要在void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)这个函数里面添加一句:打开串口接收中断的函数。

    /* USER CODE BEGIN USART1_MspInit 1 */

    __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);

    /* USER CODE END USART1_MspInit 1 */

    好了,这样通过通过空闲中段接收一帧数据的完整工程就建好了。之后就要放大招解释整个的思路了:

    首先我在初始化的时候调用__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);打开了串口的接收中断。注意这个时候我还没有打开空闲中断。而是在接收到了一个byte以后打开空闲中断。

    就这样会一直接收数据一帧的其他数据,一帧接受完以后就会出现一个空闲的时间。这个时候空闲中断就会发生。这时候我就把空闲中断和接收中断都关了。存在buf区的数据就是完整的一帧数据。

    处理完一帧数据以后我再把串口中断打开重复上面的流程,就可以完整的接收一帧一帧的数据。同时利用空闲中断也可以省去很多的的判断。

    空闲中断到底是在什么时候发生?我刚开始还理解错了,以为一上电初始化的时候打开空闲中断,假如我没有收到数据就会进入空闲中断。实际上不是这样的,空闲中断是在收到数据之后再次出现空闲的时候就会触发。所以在利用空闲中断的时候不用担心一上电就会触发了他。不过我例程里面是接收到数据以后才打开,这种情况也不用考虑了。

    展开全文
  • 求助大佬们关于STM32串口解析数据包的程序 使用的STM32CUBE IDE自带的HAL,想要通过串口发送信息给单片机. 例如给1号单片机发送233这个数据,发送格式为:编号+数据位数+数据...
  • STM32中断解析数据

    2013-11-12 11:20:42
    基于UCOS操作系统的STM32应用开发,主要为中断解析串口输出任务。程序已调试通
  • ESP8266与STM32串口数据交互

    千次阅读 2021-01-10 22:21:27
    ESP8266与STM32串口数据交互(通过JSON)ESP8266部分JSON解析库的安装功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定...
  • Python串口数据打包发送STM32接收数据解析
  • //如果在串口接收中断中接收到0x0a,数据已接收完毕`在这里插入代码片`执行 { len=USART_RX_STA&0x3fff; //得到此次接收到的数据长度,传给for循环,循环依次发出接收到的数据 printf("\r\n您...
  • 1 importos2 importtime3 importsys, traceback4 from serial.serialutil importSerialException5 from serial importSerial67 importstruct8 importbinascii91011 classArduino:12 def __init__(self, port="/d...
  • 关于STM32串口3的使用,接收并解析一帧数据 当stm32的串口1被使用时,我们可以使用其他串口来使用。 步骤: 串口3定义、初始化; 串口3中断服务函数(接收的一帧数据并判断是否正确); 主函数使用; 首先,我们要将...
  • 单片机解析GPS数据,可以输出经度,维度,UTC事件以及PPS
  • 最近在做一个小项目,需要用stm32串口接受Arduino发送的一个不定长的数据,并且解析数据,执行其中的命令;秉着不在中断中做过多任务的思想,我们将从串口中接受到的字符放到一个数组当中。  定义数组 #define ...
  • stm32串口配置步骤 完整源码 引言:在单片机的开发过程中我们通常会用到串口通讯,利用串口通讯我们可以把单片机程序运行中的一些数据传输到我们电脑或其他显示设备上来查看我们的程序是否正常运行,今天我们来讲...
  • STM32单片机的片上flash分为三个区域: IAP程序区:0x8000000~0x8004000(分16kb空间用于存储iap程序和用户信息) 说明:iap程序主要是初始化一个通信串口用于接收主控发给单片机的升级bin文件数据帧,数据帧带有...
  • 那么问题来了,现在基于stm32的Hal库把串口接收函数进行了封装,不管是非中断模式,中断模式,还是dma模式都是接收固定数量byte的数据。但是在协议处理的过程中单片机很多时候是不知道模块发过来的数据是有多少byte...
  • 文章目录功能实现背景介绍HAL库的中断接收函数状态机的运用功能实现背景介绍本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。使用的报文规则如表格所示板间报文的...
  • STM32F103C8T6开发笔记整理​zhuanlan.zhihu.com【写在前面】:这篇笔记的内容,一是要实现STM32串口的收发功能,二是要解析来自上位机发送的命令,从而控制单片机实现一些功能。通过上位机发送的不同的命令,控制...
  • 我用的是STM32库函数学的485通信,所以接下来就讲讲STM32串口实现485双机通信的原理。485和232都是基于串口的通讯接口,在数据的收发操作上都是一致的。但是他两的通讯模式却大不相同~!232是全双工(例:A->B的...
  • STM32串口发彩色图片

    2020-03-20 14:53:52
    正点原子miniSM32采集OV7725图像数据,发送给串口,上位机接收数据,并解析为bmp图片.更多请看博客,【STM32调试(一)】串口发送像素,上位机解析显示。
  • 文章目录功能实现背景介绍HAL库的中断接收函数状态机的运用功能实现背景介绍本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。使用的报文规则如表格所示板间报文的...
  • STM32F103C8T6开发笔记整理​zhuanlan.zhihu.com【写在前面】:这篇笔记的内容,一是要实现STM32串口的收发功能,二是要解析来自上位机发送的命令,从而控制单片机实现一些功能。通过上位机发送的不同的命令,控制...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 212
精华内容 84
关键字:

stm32串口解析数据