首页 > 代码库 > 环形队列
环形队列
写完这篇文章想着以后尽量(应该说一定)使用现在正在使用的LPC系列的单片机写程序,其实内心感觉还是LPC做的相当完善,,,,,配置上没有32那么的繁琐....
关于串口发送数据,自己以前呢是这样
void Usart_Out_Char(unsigned char *c,uint32_t cnt) { while(cnt--) { USART_SendData(USART1, *c++); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET ); } }
下面的调用方式
uint8_t aaa[1024]={1,2,3,42,0}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化为115200while(1) { Usart_Out_Char(aaa,1024); delay_ms(1000); PFout(6) = ~PFout(6); } }
当发送数据的时候,会一直在调用此函数的地方等着,,,,,,直至发送完所有的数据,要知道用串口中断发送数据要比这样发送快的多.......瞎耽误时间
假设现在我用中断发送
假设没有缓冲区
void UsartOutChar(unsigned char *Buff,uint32_t cnt) { dat = Buff;//把发送地址给dat BuffCnt = cnt;//记录发送的个数 USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//打开发送中断 }
void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1); //读取接收到的数据 } if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)//发送中断 { if(BuffCnt--) { USART_SendData(USART1,*dat);//发送数据 dat++; } else { //发送字节结束 USART_ClearITPendingBit(USART1,USART_IT_TXE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_TC, ENABLE); } } //发送完成 if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) { USART_ClearITPendingBit(USART1,USART_IT_TC); USART_ITConfig(USART1, USART_IT_TC, DISABLE); } }
uint8_t aaa[1024]={1,2,3,42,0}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化为115200while(1) { UsartOutChar(aaa,10); delay_ms(10); } }
加一个缓冲区---假设是下面这样子,中断发送的数据从这个缓冲区里面取
然后呢,接着又填入了
接着
假设我又想添加数据,可是呢后面空的那一块数据空间不够了......要是能把数组的尾和头联系起来就好啦......
假设加满了,,,如果能自动的加到前面就好啦.....
今天先这样...太晚啦..现在最大的愿望什么时候能安心睡个早觉..再这样下去真担心会挂了......有空再详加..
下面是实现程序--实现程序是自己想学Esp8266连接机智云的时候无意中看到的,,,,,记得 天鲁哥 曾经说过环形队列实现的很巧妙,,,改天有空再研究下当初天鲁哥给的程序
往里面加数据尾指针向右增加...加到头回到首地址
从里面读数据头指针向右增加...加到头回到首地址
注意
还是在唠叨唠叨
rb_t pRb; ///< 环形缓冲区结构体变量 uint8_t rbBuf[RB_MAX_LEN]; ///< 环形缓冲区数据缓存区 void rbCreate(rb_t* rb,u8 *Buff,uint32_t BuffLen)//创建或者说初始化环形缓冲区 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return; } rb->rbCapacity = BuffLen; rb->rbBuff = Buff; rb->rbHead = rb->rbBuff;//头指向数组首地址 rb->rbTail = rb->rbBuff;//尾指向数组首地址 } void rbDelete(rb_t* rb)//删除一个环形缓冲区 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return; } rb->rbBuff = NULL;//地址赋值为空 rb->rbHead = NULL;//头地址为空 rb->rbTail = NULL;//尾地址尾空 rb->rbCapacity = 0;//长度为空 } int32_t rbCapacity(rb_t *rb)//获取链表的长度 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } return rb->rbCapacity; } int32_t rbCanRead(rb_t *rb)//返回能读的空间 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } if (rb->rbHead == rb->rbTail)//头与尾相遇 { return 0; } if (rb->rbHead < rb->rbTail)//尾大于头 { return rb->rbTail - rb->rbHead; } return rbCapacity(rb) - (rb->rbHead - rb->rbTail);//头大于尾 } int32_t rbCanWrite(rb_t *rb)//返回能写入的空间 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } return rbCapacity(rb) - rbCanRead(rb);//总的减去已经写入的空间 } /* rb--要读的环形链表 data--读出的数据 count--读的个数 */ int32_t rbRead(rb_t *rb, void *data, size_t count) { int copySz = 0; if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } if(NULL == data) { printf("ERROR: input data is NULL\n"); return -1; } if (rb->rbHead < rb->rbTail)//尾大于头 { copySz = min(count, rbCanRead(rb));//查看能读的个数 memcpy(data, rb->rbHead, copySz);//读出数据到data rb->rbHead += copySz;//头指针加上读取的个数 return copySz;//返回读取的个数 } else //头大于等于了尾 { if (count < rbCapacity(rb)-(rb->rbHead - rb->rbBuff))//读的个数小于头上面的数据量 { copySz = count;//读出的个数 memcpy(data, rb->rbHead, copySz);// rb->rbHead += copySz; return copySz; } else//读的个数大于头上面的数据量 { copySz = rbCapacity(rb) - (rb->rbHead - rb->rbBuff);//先读出来头上面的数据 memcpy(data, rb->rbHead, copySz); rb->rbHead = rb->rbBuff;//头指针指向数组的首地址 //还要读的个数 copySz += rbRead(rb, (char*)data+copySz, count-copySz);//接着读剩余要读的个数 return copySz; } } } int32_t rbWrite(rb_t *rb, const void *data, size_t count) { int tailAvailSz = 0; if(NULL == rb) { printf("ERROR: rb is empty \n"); return -1; } if(NULL == data) { printf("ERROR: data is empty \n"); return -1; } if (count >= rbCanWrite(rb))//如果剩余的空间不够 { printf("ERROR: no memory \n"); return -1; } if (rb->rbHead <= rb->rbTail)//头小于等于尾 { tailAvailSz = rbCapacity(rb) - (rb->rbTail - rb->rbBuff);//查看尾上面剩余的空间 if (count <= tailAvailSz)//个数小于等于尾上面剩余的空间 { memcpy(rb->rbTail, data, count);//拷贝数据到环形数组 rb->rbTail += count;//尾指针加上数据个数 if (rb->rbTail == rb->rbBuff+rbCapacity(rb))//正好写到最后 { rb->rbTail = rb->rbBuff;//尾指向数组的首地址 } return count;//返回写入的数据个数 } else { memcpy(rb->rbTail, data, tailAvailSz);//填入尾上面剩余的空间 rb->rbTail = rb->rbBuff;//尾指针指向数组首地址 //剩余空间 剩余数据的首地址 剩余数据的个数 return tailAvailSz + rbWrite(rb, (char*)data+tailAvailSz, count-tailAvailSz);//接着写剩余的数据 } } else //头大于尾 { memcpy(rb->rbTail, data, count); rb->rbTail += count; return count; } } /**@} */ /** * @brief 向环形缓冲区写入数据 * @param [in] buf : buf地址 * @param [in] len : 字节长度 * @return 正确 : 返回写入的数据长度 失败 : -1 */ int32_t PutData(uint8_t *buf, uint32_t len) { int32_t count = 0; if(NULL == buf) { printf("ERROR: gizPutData buf is empty \n"); return -1; } count = rbWrite(&pRb, buf, len); if(count != len) { printf("ERROR: Failed to rbWrite \n"); return -1; } USART_ITConfig(USART1, USART_IT_TXE, ENABLE); return count; }
#ifndef LOOPLIST_H_ #define LOOPLIST_H_ #ifndef LOOPLIST_C_//如果没有定义 AnnularArray_C_ #define LOOPLIST_C_ extern #else #define LOOPLIST_C_ #endif #include <stm32f10x.h> #define size_t uint16_t #define RB_MAX_LEN 1024 //缓冲区最大长度 #define min(a, b) (a)<(b)?(a):(b) ///< 获取最小值 /** 环形缓冲区数据结构 */ typedef struct { size_t rbCapacity;//空间大小 uint8_t *rbHead; //头 uint8_t *rbTail; //尾 uint8_t *rbBuff; //数组的首地址 }rb_t; LOOPLIST_C_ rb_t pRb; ///< 环形缓冲区结构体变量 LOOPLIST_C_ uint8_t rbBuf[RB_MAX_LEN]; ///< 环形缓冲区数据缓存区 LOOPLIST_C_ void rbCreate(rb_t *rb,u8 *Buff,uint32_t BuffLen);//创建或者说初始化环形缓冲区 LOOPLIST_C_ void rbDelete(rb_t* rb); LOOPLIST_C_ int32_t rbCapacity(rb_t *rb);//得到环形大小 LOOPLIST_C_ int32_t rbCanRead(rb_t *rb);//能读出数据的个数 LOOPLIST_C_ int32_t rbCanWrite(rb_t *rb);//还剩余的空间 LOOPLIST_C_ int32_t rbRead(rb_t *rb, void *data, size_t count);//读取数据 LOOPLIST_C_ int32_t rbWrite(rb_t *rb, const void *data, size_t count); LOOPLIST_C_ int32_t PutData(uint8_t *buf, uint32_t len); #endif
使用就很方便了--直接往里面填数据就好啦
#include "include.h" uint8_t aaa[50]={1,1,1,1,1,1,1,1,1,1}; uint8_t bbb[50]={3,3,3,3,3,3,3,3,3,3}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化为115200 rbCreate(&pRb,SendBuff,USART_REC_LEN);//创建环形队列 while(1) { PutData(aaa,10);//发送数据 PutData(bbb,10);//发送数据 delay_ms(10); } }
void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1); //读取接收到的数据 } if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { if(rbCanRead(&pRb)>0)//如果里面的数据个数大于0 { rbRead(&pRb, &SendDat, 1);//读取一个数据 USART_SendData(USART1, SendDat);//发送 } else { //发送字节结束 USART_ClearITPendingBit(USART1,USART_IT_TXE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_TC, ENABLE); } } //发送完成 if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) { USART_ClearITPendingBit(USART1,USART_IT_TC); USART_ITConfig(USART1, USART_IT_TC, DISABLE); } }
其实再完美点就是加上DMA....后期我尽量用LPC的单片机做....不对是一定要用LPC的单片机做成dma的---
程序链接:http://pan.baidu.com/s/1pLlXDfP 密码:6kci
环形队列
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。