一、FIFO是First Input First Output的缩写,先入先出队列 。
使用的场景:一般是在不同的时钟域之间的数据传输(简单理解即:一个(读写)快,另外的一个(读写)慢的场景中 。)
本质操作:就是将收的数据存储的一个线性的数组中,通过指针指向该数组的自加1(偏移)来遍历数据,达到读取或者写入的目的 。
作用:起到缓冲环节,可防止数据的丢失 。
对数据量大的进行存储,避免频繁的总线操作 。并且可满足dma的操作 。
在fifo中需要理解连个重要成员:
宽度:指一次写读操作的数据位数 。
深度:存储多少个宽度的数据 。(如:存储8个16位宽的数据) 。
第一类、FIFO处理机制如下:FIFO信息的定义:
/*该结构体定义成员有缓存区,长度,输出,输入的计数 。*/typedef struct fifo_t {uint8_t *buf; uint32_t size; uint32_t in; uint32_t out;} _fifo_str;#define min(x,y) ((x) < (y)?(x):(y))1234567891011121314
1、初始化FIFOfifo_str fifo_str;int FifoInit(uint8_t *fifo_addr, uint32_t fifo_size)//初始化fifo{ _fifo_str *p = &fifo_str;if(fifo_addr == NULL || fifo_size == 0)//判断数据是否为空return -1; memset((char *)p, 0, sizeof(_fifo_str));//初始化结构体 p->buf = fifo_addr;//对应宽度p->in = 0;//输入计数p->out = 0;//输出计数p->size = fifo_size;//对应深度 return 0;}12345678910111213141516
2、数据的长度获取//数据的实际使用数据空间长度int FifoDataLen(void){ _fifo_str *p = &fifo_str; return (p->in - p->out);//输入计数-输出计数}//剩余数据空间长度int FifoSpaceLen(void){ _fifo_str *p = &fifo_str;return (p->size - (p->in - p->out));//定义长度-(实际长度)}12345678910111213
3、FIFO的进和出处理//获取fifo数据//数据的内容缓存区,要读的长度int FifoRead(uint8_t *buf, uint32_t len){ uint32_t i = 0, j = 0; _fifo_str *p = &fifo_str; j = (p->out % p->size);//获取剩余空间长度未读量 len = min(len, p->in - p->out);//防止长度为超出实际拥有的数据长度,即让读取的长度在(0<设定len<定义的缓存区长度len )这间的实际长度 i = min(len, p->size - j);//获取实际内容的长度,的数据长度 memcpy(buf, p->buf + j, i);//将数据通道里的数据拷贝给缓存区 memcpy(buf + i, p->buf, len - i);//将未有数据的区域存入,对应为写入数据的区域数据(即,有数据的填数据,没数据的地方补0) p->out += len;//已读的数据量 return len;//实际读到的数据长度}//对fifo写入数据int FifoWrite(uint8_t *buf, uint32_t len){ uint32_t i = 0, j = 0; _fifo_str *p = &fifo_str; j = p->in % p->size;//获取要写入的剩余空间长度 len = min(len, p->size - p->in + p->out);//得到实际写入的长度 i = min(len, p->size - j);//实际写入数据的长度 memcpy(p->buf + j, buf, i);//将写入的数据的内容拷贝值数据中 。memcpy(p->buf, buf + i, len - i);//补充多余空间的内容 p->in += len;//记录实际写入数据的数量 return len;//返回写入的长度}123456789101112131415161718192021222324252627282930
4、置位记录量//清空fifo 中的记录量void FifoClear(void){ _fifo_str *p = &fifo_str;p->in = 0;p->out = 0;}1234567
5、应用处理机制#define LEN 2048uint8_t pdata[LEN] = {0};FifoInit(pdata, LEN);//初始化FIFOuint8_t buf[32] = {0}; int tx_len = 0;uint8_t tx_buf[100] = {0};HAL_UART_Receive_IT(&huart1, buf, IT_LEN);//串口的接收中断开启while(1) {tx_len = FifoDataLen();//获取数据长度if (tx_len > 0){tx_len = (tx_len > 100) ? 100 : tx_len;//判读数据长度是否越界FifoRead(tx_buf, tx_len);//读取在中断中写入FIFO缓存的数据HAL_UART_Transmit(&huart1, tx_buf, tx_len, 1000);//将读到的数据通过串口发送出来} }接收回调函数中的处理HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (FifoSpaceLen() >= 串口记录的接收数据长度)//判断写入FIFO空间的数据量是否大于接收的数据量 {FifoWrite(huart->pRxBuffPtr, huart->RxXferCount);//想FIFO中写入数据 }} 123456789101112131415161718192021222324252627
该FIFO的处理机制中用的记录是通过uint32t类型进行记录的,可能在遇到超出其数据极限的情况,导致数据通信异常 。(该类型的数据极限较大,为特殊情况可能出现的情况) 。
第二类、FIFO处理机制如下:/* 定义串口波特率和FIFO缓冲区大小,分为发送缓冲区和接收缓冲区*/ #if UART1_FIFO_EN == 1#define UART1_BAUD 115200#define UART1_TX_BUF_SIZE 1*1024#define UART1_RX_BUF_SIZE 1*1024#endif /* 串口设备结构体 设置发送、接收缓存区(长度),并设置两个变量,一个是指针,一个是计数 */ typedef struct {USART_TypeDef *uart; /* STM32内部串口设备指针 */uint8_t *pTxBuf; /* 发送缓冲区 */uint8_t *pRxBuf; /* 接收缓冲区 */uint16_t usTxBufSize; /* 发送缓冲区大小 */uint16_t usRxBufSize; /* 接收缓冲区大小 */__IO uint16_t usTxWrite; /* 发送缓冲区写指针 */__IO uint16_t usTxRead; /* 发送缓冲区读指针 */__IO uint16_t usTxCount; /* 等待发送的数据个数 */__IO uint16_t usRxWrite; /* 接收缓冲区写指针 */__IO uint16_t usRxRead; /* 接收缓冲区读指针 */__IO uint16_t usRxCount; /* 还未读取的新数据个数 */void (*SendBefor)(void); /* 开始发送之前的回调函数指针(主要用于RS485切换到发送模式) */void (*SendOver)(void); /* 发送完毕的回调函数指针(主要用于RS485将发送模式切换为接收模式) */void (*ReciveNew)(uint8_t _byte); /* 串口收到数据的回调函数指针 */uint8_t Sending; /* 正在发送中 */ }UART_T;/* 定义每个串口结构体变量 */ #if UART1_FIFO_EN == 1static UART_T g_tUart1; static uint8_t g_TxBuf1[UART1_TX_BUF_SIZE]; /* 发送缓冲区 */static uint8_t g_RxBuf1[UART1_RX_BUF_SIZE]; /* 接收缓冲区 */ #endif12345678910111213141516171819202122232425262728293031323334353637383940414243
推荐阅读
- 手机wifi经常断网、掉线,接收消息延迟?原来是这个开关没打开
- 马云|洪金宝对马云的评价,实在是太直白了!
- 陈钰琪|对不起!带着《香蜜》的滤镜,我也接受不了陈钰琪跟王鹤棣演CP
- 幼儿园家长寄语对老师的话?幼儿园家长对老师寄语大全_2
- 科幻|国产科幻游戏《戴森球计划》大更新预告:对阵浩瀚星河舰队
- 寺庙对联集萃 寺庙对联
- 差价最高9000元,华为Mate 50系列怎么选?配置详细对比一文看懂
- |领导看到你在努力工作,对你会有所赏识
- 成吉思汗西征死了多少士兵?成吉思汗的部队
- 小米12对比小米mix4?小米12比小米mix4更香