一:队列的基础知识分享:
队列是一种先进先出(FIFO)的线性数据结构,只允许在队尾插入元素,在队头删除元素。对于队列的操作包括:入队,出队,查看队头元素,判断队列是否为空的操作。
基本特性:先进先出的原则,最先进入队列的元素,最先被移除队列。
主要操作:
入队(enqueue):在队列的尾端添加元素。
出队(dequeue):在队列的首端移除元素。
队列的实现方式如下所示:
1:数组实现:
使用固定大小的数组
需要处理循环队列的情况以避免空间浪费
2:链表实现:
使用单向链表,头指针指向队首,尾指针指向队尾
不需要预先分配固定大小
二:队列相关代码分享:
2.1 队列的初始化:
- /**************************************************************************
- - 功能描述:队列初始化
- - 参数说明:*s 队列句柄 *buf 队列结构体数据地址
- - 返回说明:-1 失败 0 成功
- **************************************************************************/
- int Initquene(squene *s, QelemType *buf)
- {
- s->base=buf;
- if(!s->base)
- return -1;
- s->front=0;
- s->rear=0;
- return 0;
- }
2.2 入队列操作
- /**************************************************************************
- - 功能描述:入队列
- - 参数说明:*s 队列句柄 *e 要入队列数据的地址
- - 返回说明:无
- **************************************************************************/
- void enquene(squene *s,QelemType *e)
- {
- if(((s->rear)+1)%MAXSIZE==s->front)
- {
- return ;
- }
- memcpy(&(s->base[s->rear]), e, sizeof(QelemType));
- s->rear=((s->rear)+1)%MAXSIZE;
- }
2.3 出队列操作:
- /**************************************************************************
- - 功能描述:出队列
- - 参数说明:*s 队列句柄 *e 出队列数据要写入的地址
- - 返回说明:-1 失败 0 成功
- **************************************************************************/
- int dequene(squene *s,QelemType *e)
- {
- if(s->rear==s->front)
- {
- return -1;
- }
- memcpy(e, &(s->base[s->front]), sizeof(QelemType));
- memset(&(s->base[s->front]), 0, sizeof(QelemType));
- s->front=((s->front)+1) % MAXSIZE;
- return 0;
- }
2.4 初始化所用的队列
- /**************************************************************************
- - 功能描述:初始化所有应用的队列
- - 参数说明:void
- - 返回说明:void
- **************************************************************************/
- void Queue_Init(void)
- {
- Initquene(&QUsart4Tx, QUsart4TxData);
- }
三:噪音传感器如下所示:
AS11-x是采用原装进口声音传感器开发的直读式噪音分贝检测模块
多点标定工艺制作、检测精度高、灵敏度高独特的不绣钢探头
独立封装设计、方便嵌入其它的设备或机壳!
主控板电路核心器件完全屏蔽、不仅美观更加强抗干扰能力
预留多种输出 TTL/I2C、标准 Modbus Rtu 通讯 485 接口可选,适用于各种应用集成。
modbus 协议如下所示:
四:CH32代码如下所示:
4.1 串口3的初始化:
- void USART3_Init(int baud)
- {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- USART_InitTypeDef USART_InitStructure = {0};
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3 , ENABLE );
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE );
- /* USART3 TX-->B.10 RX-->B.11 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init( GPIOB, &GPIO_InitStructure );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init( GPIOB, &GPIO_InitStructure );
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- /* Enable USART3 Receive and Transmit interrupts */
- USART_DMACmd(USART3, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE); //使能USART2的收发DMA
- USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
- USART_ITConfig(USART3, USART_IT_TC, ENABLE);//开启发送完成中断
- USART_Init( USART3, &USART_InitStructure );
- DMA_USART3_TX_Configuration(2);//发送2个空字节
- DMA_USART3_RX_Configuration();
- DMA_Cmd( DMA1_Channel2, ENABLE ); /* USART3 Tx */
- DMA_Cmd( DMA1_Channel3, ENABLE ); /* USART3 Rx */
- NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- USART_Cmd( USART3, ENABLE );
- }
4.2 串口3的发送函数:
- /*******************************************************************************
- * Function Name : bool SendDataToUSART2(char length)
- * Description : Enable Transimt Interrupt and sart Send
- * Input : Send data Buf Length
- * Output : None
- * Return : NOne
- *******************************************************************************/
- bool SendDataToUSART3(char length)
- {
- //等待DMA发送完毕后,即可以启动发送
- /* Wait until DMA1_Channel 7 Transfer Complete */
- volatile u16 uDataCounter;
- uDataCounter = DMA_GetCurrDataCounter(DMA1_Channel2);
- while (uDataCounter > 0)
- {
- uDataCounter = DMA_GetCurrDataCounter(DMA1_Channel2);
- }
- DMA_USART3_TX_Configuration(length);
- DMA_Cmd(DMA1_Channel2, ENABLE); //开启DMA发送
- return TRUE;
- }
4.3 读取噪音传感器的指令如下所示:
- /***********************************************************************
- 函数名:Read_Register_Modbus()
- 函数功能:读取寄存器
- 参数: modbus_addr //从机地址
- addr //起始寄存器地址
- ucount //寄存器数量
- *****************************************************************/
- void Read_Register_Modbus(unsigned char modbus_addr,unsigned int addr,unsigned int ucount)
- {
- uint16_t CRCData;
- QelemType Data = {0};
- Data.uLength =8;
- Data.buffer[0] = modbus_addr;
- Data.buffer[1] = 0x03;
- Data.buffer[2] = addr >>8;
- Data.buffer[3] = addr;
- Data.buffer[4] = ucount >>8;
- Data.buffer[5] = ucount; //SUM
- CRCData = mb_crc16(&Data.buffer[0],6);
- Data.buffer[6] = CRCData >>8;
- Data.buffer[7] = CRCData; //SUM
- enquene(&QUsart4Tx,&Data);
- }
4.4 直接在串口的空闲中断将RS485收到的数据进行解析
- void UART3_Rec_Deal(void)
- {
- if(usart3_Flag == 1)
- {
- usart3_Flag = 0 ;
- if((Usart3_DEAL_RX_Buf[0] == 0x01)&&(Usart3_DEAL_RX_Buf[1] == 0x03))
- {
- EnvirMentPara.uiNoise = ( Usart3_DEAL_RX_Buf[3] << 8 ) +Usart3_DEAL_RX_Buf[4] ;
- }
- memset(Usart3_DEAL_RX_Buf,0,reclength3);
- }
- }
五:实物测试如下所示:
|