环形缓冲区的问题,,,,,,,,,,,,,,,,

2019-07-21 03:18发布

是这样的,之前那个CO2传感器接收到的数据是乱的,所以想用环形缓冲区解决这个问题,但对环形缓冲区了解的不多,请大神指点指点,谢谢

#include "MyRingBuf.h"
#include "CO2_Sensor.h"
#include "string.h"
#include "stdbool.h"

void RingBufInit(RingBuf_TypeDef* ringBuf)         //环形缓冲区初始化
{
  memset(ringBuf, 0, sizeof(RingBuf_TypeDef));
  ringBuf->pHead = ringBuf->pTail = ringBuf->buf;
}

bool RingBufRead(uint8_t* pData, RingBuf_TypeDef* ringBuf)      //读缓冲区
{
  if(ringBuf->pHead == ringBuf->pTail) //如果头尾接触表示缓冲区为空
  {
    return false;
  }
  else
  {
    *pData = *(ringBuf->pTail); //如果缓冲区非空则取头节点值并偏移头节点
    ringBuf->pTail += 1;
    if((uint32_t)ringBuf->pTail >= (uint32_t)ringBuf->buf+RING_BUF_LEN)
      ringBuf->pTail = ringBuf->buf;

    return true;
  }
}

bool RingBufWrite(uint8_t* pData, RingBuf_TypeDef* ringBuf)      //写缓冲区
{
  if(ringBuf->pHead == ringBuf->pTail) //如果头尾接触表示缓冲区为空
  {
    return false;
  }
  else
  {
     *(ringBuf->pHead) = *pData; //如果缓冲区非空则取头节点值并偏移头节点
    ringBuf->pHead += 1;
    if((uint32_t)ringBuf->pHead >= (uint32_t)ringBuf->buf+RING_BUF_LEN)
      ringBuf->pHead = ringBuf->buf;

    return true;
  }
}

uint8_t* GetRingBufTail(const RingBuf_TypeDef* ringBuf)
{
  return ringBuf->pTail;
}

uint8_t* GetRingBufHead(const RingBuf_TypeDef* ringBuf)
{
  return ringBuf->pHead;
}

void MoveRingBufTail(RingBuf_TypeDef* ringBuf, uint16_t len)
{
  ringBuf->pTail -= len;
  if (ringBuf->pTail < ringBuf->buf)
    ringBuf->pTail += RING_BUF_LEN;
}

/**
* @brief读取环形缓冲区的字符,直到以指定结束字符
* @param *recBuf:接收buffer,用于保存读取到的数据
* @param ringBuf:环形缓冲区
* @param len:    长度
* @return 成功或失败
*/
bool ReadRingBuffToChar(uint8_t* recBuf,RingBuf_TypeDef* ringBuf, uint16_t len)    //读取缓冲区字符
{
  uint8_t* p = recBuf;
  for (uint16_t i = 0; i < len; i++)
  {
    if (!RingBufRead(p++, ringBuf))
      return false;
  }
  return true;
}


这个是创建一个环形缓冲区;;;;


#include "CO2_Sensor.h"
#include "MyRingBuf.h"
#include "timer.h"
#include "usart.h"
#include "MyUsart.h"

CO2Sensor CO2;

void CO2_config(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);

  SysTick_Config_Init();
  CO2_gpio_config();
  CO2_usart_config();
  co2_nvic_config();
  //co2_receivedata();
  co2_data_anl();
  usart_config();
  CO2_unpack();
}

void CO2_gpio_config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;      //USART6
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_Init(GPIOC,&GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_2);         //TX            
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_2);         //RX           
}

void CO2_usart_config(void)
{
  USART_InitTypeDef USART_InitStructure;

  USART_InitStructure.USART_BaudRate = 9600;         /*波特率*/
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   /*流控*/
  USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;    /*数据位,8*/
  USART_InitStructure.USART_Parity = USART_Parity_No;            /*校验位,n*/
  USART_InitStructure.USART_StopBits = USART_StopBits_1;         /*停止位,1*/
  USART_Init(USART6,&USART_InitStructure);

  USART_ClearFlag(USART6,USART_FLAG_TC);                    //清除发送完成标志位
  USART_Cmd(USART6,ENABLE);                                 //使能串口3

  USART_ITConfig(USART6,USART_IT_RXNE,ENABLE);
}

void co2_nvic_config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannel = USART3_6_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

void CO2_Sensor_interrupt(void)
{
  uint8_t receive_data;

  if(USART_GetITStatus(USART6,USART_IT_RXNE) != RESET)
  {
    USART_ClearITPendingBit(USART6,USART_IT_RXNE);
    receive_data = USART_ReceiveData(USART6);                 //接收USART6的数据
    CO2.data_buf[CO2.counter] = receive_data;
    CO2.counter++;

    if(CO2.counter > 11)
    {
      CO2.counter = 0;
    }
  }
}

void co2_sendata(void)
{
  CO2.sendbuf[0] = 0x42;
  CO2.sendbuf[1] = 0x4D;
  CO2.sendbuf[2] = 0xE3;
  CO2.sendbuf[3] = 0x58;
  CO2.sendbuf[4] = 0x58;
  CO2.sendbuf[5] = 0x02;
  CO2.sendbuf[6] = 0x22;
  usart_send_data(USART6,CO2.sendbuf,7);
}



void CO2_unpack(void)
{
  for (int i = 0; i < 12; i++)
  {
    if (CO2.data_buf[i] == 0x42 && CO2.data_buf[(i+1)%12] == 0x4D)
    {
      CO2.ppm = (int)CO2.data_buf[(i+4)%12]*256+(int)CO2.data_buf[(i+5)%12];
    }
    co2_data_anl();
  }
}

uint8_t co2_data_anl(void)     //解析数据
{
  for(CO2.counter = 0; CO2.counter < 10; CO2.counter++)
  {
    CO2.total += CO2.data_buf[CO2.counter];
  }

  CO2.total1 = CO2.data_buf[10] + CO2.data_buf[11];

  if(CO2.total == CO2.total1)
  {
    return CO2.total1;             //校验正确
  }
  else
  {
    return 0;             //校验错误
  }
}


这是传感器部分的代码,,求大神指点一下谢谢;
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
nashui_sx
1楼-- · 2019-07-21 07:35
本帖最后由 nashui_sx 于 2019-4-10 09:38 编辑

说实话,这个传感器你都搞不定真没必要用环形队列给自己找麻烦,串口空闲中断就足够了
你贴出来一帧数据 ,有校验,校验函数贴出来,我给你改一个,论坛都n个人发过了


非要用fifo方式,安富莱的串口就是fifo做的,下载一个就好了
1599064432
2楼-- · 2019-07-21 11:15
nashui_sx 发表于 2019-4-10 09:32
说实话,这个传感器你都搞不定真没必要用环形队列给自己找麻烦,串口空闲中断就足够了
你贴出来一帧数据  ...

void CO2_Sensor_interrupt(void)
{
  uint8_t receive_data;

  if(USART_GetITStatus(USART6,USART_IT_RXNE) != RESET)
  {
    USART_ClearITPendingBit(USART6,USART_IT_RXNE);
    receive_data = USART_ReceiveData(USART6);                 //接收USART6的数据
    CO2.data_buf[CO2.counter] = receive_data;
    CO2.counter++;
   
    if(CO2.counter > 11)
    {
      CO2.counter = 0;
    }
  }
}

void co2_sendata(void)
{
  CO2.sendbuf[0] = 0x42;
  CO2.sendbuf[1] = 0x4D;
  CO2.sendbuf[2] = 0xE3;
  CO2.sendbuf[3] = 0x58;
  CO2.sendbuf[4] = 0x58;
  CO2.sendbuf[5] = 0x02;
  CO2.sendbuf[6] = 0x22;
  usart_send_data(USART6,CO2.sendbuf,7);
}

void CO2_unpack(void)
{
  for (int i = 0; i < 12; i++)
  {
    if (CO2.data_buf == 0x42 && CO2.data_buf[(i+1)%12] == 0x4D)
    {
      CO2.ppm = (int)CO2.data_buf[(i+4)%12]*256+(int)CO2.data_buf[(i+5)%12];
    }
    co2_data_anl();
  }
}

uint8_t co2_data_anl(void)     //解析数据
{
  for(CO2.counter = 0; CO2.counter < 10; CO2.counter++)
  {
    CO2.total += CO2.data_buf[CO2.counter];
  }
  
  CO2.total1 = CO2.data_buf[10] + CO2.data_buf[11];
  
  if(CO2.total == CO2.total1)
  {
    return CO2.total1;             //校验正确
  }
  else
  {
    return 0;             //校验错误
  }
}
nashui_sx
3楼-- · 2019-07-21 16:11
本帖最后由 nashui_sx 于 2019-4-10 09:48 编辑
1599064432 发表于 2019-4-10 09:39
void CO2_Sensor_interrupt(void)
{
  uint8_t receive_data;

我的意思是一帧数据例如FF 86 00 00 00 00 00 00 7A
7A和校验,你把校验函数你写好的贴出来例如下面的格式发出来
142044h3jcvxlyeeiizfzv.png

1599064432
4楼-- · 2019-07-21 21:20
 精彩回答 2  元偷偷看……
nashui_sx
5楼-- · 2019-07-22 01:32
本帖最后由 nashui_sx 于 2019-4-10 09:54 编辑
1599064432 发表于 2019-4-10 09:49
一共12个字节,42 4d 00 00 00 00 00 00 00 00 校验 校验

uint8_t co2_data_anl(void)     //解析数据 ...

校验是啥校验 crc 和校验,你就不能思考下一次回复完美点我有没有传感器,类似上一楼的截图,你介绍下12字节每一位的意思,再给一帧传感器返回的正确数据,我用串口助手才能模拟传感器呀,
1599064432
6楼-- · 2019-07-22 01:53
nashui_sx 发表于 2019-4-10 09:51
校验是啥校验 crc 和校验,你就不能思考下一次回复完美点

QQ截图20190410095203.png

一周热门 更多>