| 利用STM32 中断进行串口数据读写,由于引入中断机制,串口的读是放在中断回调函数中,由于中断的高速性,很容易引起指定的缓存区满,因此增加串口读缓冲队列,是保证数据高效可靠的保证。 STM32中,没有高级操作系统中的线程调度这一概念,也就无锁的概念,但是中断的优先级高,会不停的打断主程序的执行,当主程序重回中断向量位置时,由于中断对一些数据状态的改变,主程序很容易读到脏数据。因为缓冲队列是作为公共缓冲区的中转场合,势必会造成中断部分与主程序部分的争用问题,为了解决这种竞态争用队列的问题,采用传统的递归扫描队列中的环形数组状态的方法,就不可行了,递归的过程中很容易读到脏数据了。 分析中发现,由于缓冲区较大,读、写部分,是对缓冲区中的不同部分来分开处理的,因此可以把公共竞态的部分,缩小,缩小到状态位的处理,这样争用就少了,但是单独靠状态位,无方向性,因此引入了计数器,只需要比较读、写状态的计数差值,就知道了当前读、写的区间段,为了保证环形数组构造的队列的可循环性,还需要引入游标机制,来确定读、写部分的当前位,游标读、写独立游标,二者唯一需要交互的就是计数器了,利用此方法解决竞态问题。这种机制由于不是高级操作系统的锁那种在CPU上强制做排他处理,因此队列部分无法满足多个输入中断同时进入,多个中断之间的计数会引起竞态。 [objc] view plain copy
 
 
 ReceiveBufferData receiveBufferQueue[20];//½ÓÊÕ¶ÓÁР int writeBufferQueueCursor=0;//½ÓÊÕ¶ÓÁеÄѹÈëÓαꠠint writeBufferQueueCount=0;//×ܼÆÐ´¶ÓÁеĴÎÊý  int readBufferQueueCursor=0;//½ÓÊÕ¶ÓÁеĶÁÈ¡Óαꠠint readBufferQueueCount=0;//×ܼƳɹ¦¶Á¶ÓÁеĴÎÊý  int receiveBufferQueueLen=20;//½ÓÊÕ¶ÓÁг¤¶È  ReceiveBufferData emptyReceiveBufferData;//¿ÕµÄÊý¾Ý£¬ÓÃÓÚ¿ÕÅųöʹÓà //ѹÈë½ÓÊÕÊý¾Ý°üµ½¶ÓÁР void PushReceiveBufferData(u8 *tempReceiveBuffer,u8 receiveLen)  {       int i=0;     int tempWriteBufferQueueCursor=writeBufferQueueCursor;       ReceiveBufferData receiveItem;       writeBufferQueueCursor+=1;       if(writeBufferQueueCursor==receiveBufferQueueLen)       {        writeBufferQueueCursor=0;     }       receiveBufferQueue[writeBufferQueueCursor].ReceiveStatus=0x00;       receiveItem=receiveBufferQueue[tempWriteBufferQueueCursor];       receiveItem.ReceiveLength=receiveLen;       for(i=0;i<receiveLen;i++)       {           *(receiveItem.ReceiveBuffer+i)=*(tempReceiveBuffer+i);     }       receiveItem.ReceiveStatus=0x01;       receiveBufferQueue[tempWriteBufferQueueCursor]=receiveItem;       writeBufferQueueCount+=1;  }  //µ¯³öÐèÒª´¦ÀíµÄ½ÓÊÕÊý¾Ý°ü  ReceiveBufferData PopReceiveBufferData()  {      int tempReadBufferQueueCursor=readBufferQueueCursor;      ReceiveBufferData receiveItem;      if(readBufferQueueCount>=writeBufferQueueCount)      {       emptyReceiveBufferData.ReceiveStatus=0x00;         return emptyReceiveBufferData;    }      readBufferQueueCursor+=1;      if(readBufferQueueCursor==receiveBufferQueueLen)      {       readBufferQueueCursor=0;    }      receiveItem=receiveBufferQueue[tempReadBufferQueueCursor];      if(receiveItem.ReceiveStatus==0x01)      {         receiveItem.ReceiveStatus=0x02;      }      receiveBufferQueue[tempReadBufferQueueCursor]=receiveItem;      readBufferQueueCount+=1;      return receiveItem;  }  
 
 
 |