【平头哥RVB2601创意应用开发】模拟UART之三 实现FIFO接收
[复制链接]
硬件的串口是有FIFO功能的,这样接收进来的数据会放到缓冲区里。由于GPIO摸拟的没有缓冲,所以就自己“抄”了一个FIFO的作品。
fifi.c
/**************FIFO Begin**************************************************/
/*溢出标志:0-正常,-1-溢出*/
#include <board.h>
#include <aos/aos.h>
#define TAG "FFO:"
#define FLAGS_OVERRUN 0x0001
aos_mutex_t test_mutex;
/*
buf- 缓冲区地址
size- 大小
free- 空余容量
putP- 下一个数据写入位置
getP- 下一个数据独处位置
*/
struct FIFO8{
char *buf;
int putP,getP,size,free,flags;
aos_mutex_t mutex;
};
struct FIFO8 _FIFO8;
int fifo8_init(struct FIFO8 *fifo,int size);
int fifo8_putPut(struct FIFO8 *fifo, char data); //not mutiply thread safe
int fifo8_get(struct FIFO8 *fifo); //not mutiply thread safe
void fifo8_status(struct FIFO8 *fifo,int *len);
void fifo8_free(struct FIFO8 *fifo,int *len);
int fifo8_write(struct FIFO8 *fifo,char *data,int len);
int fifo8_read(struct FIFO8 *fifo,char *data,int len);
/*初始化*/
int fifo8_init(struct FIFO8 *fifo,int size) {
int ret=0;
fifo->flags=0;
fifo->free=size;
fifo->size=size;
fifo->putP=0;
fifo->getP=0;
fifo->buf=(char *)malloc(size);
if(fifo->buf == NULL){
LOGD(TAG,"malloc fifo buffer failed!\n");
return -1;
}
ret = aos_mutex_is_valid(&fifo->mutex);
if(ret <0){
LOGD(TAG,"init mutex failed!\n");
return -1;
}
LOGD(TAG,"init mutex OK!\n");
return 0;
}
/*向FIFO 中写入1个数据 */
int fifo8_putPut(struct FIFO8 *fifo, char data) {
if(fifo->free==0){
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->putP] = data;
fifo->putP++;
//循环队列缓冲区
if(fifo->putP == fifo->size){
fifo->putP = 0;
}
fifo->free--;
return 0;
}
/*从FIFO 中取出一个数据 */
int fifo8_get(struct FIFO8 *fifo) {
int data;
if(fifo->free == fifo->size){
return -1;
}
data = fifo->buf[fifo->getP++];
//fifo->getP++;
if(fifo->getP == fifo->size){//用来实现循环
fifo->getP = 0;
}
fifo->free++;
return data;
}
/*写入len个字节,返回写入的字节数*/
int fifo8_write(struct FIFO8 *fifo,char *data,int len){
int i=0;
aos_mutex_lock(&(fifo->mutex), AOS_WAIT_FOREVER);
if(fifo->free < len) {
aos_mutex_unlock(&(fifo->mutex));
LOGD(TAG,"the free size in not enough!\n");
return 0;
}
else {
LOGI(TAG,"current fifo->putP =%d \n",fifo->putP);
for(i=0;i<len;i++){
fifo->buf[fifo->putP++] = *(data+i);
//循环队列缓冲区
if(fifo->putP == fifo->size){
fifo->putP = 0;
}
fifo->free--;
}
}
aos_mutex_unlock(&(fifo->mutex));
return len;
}
/*读出len个字节,返回读出的字节数*/
int fifo8_read(struct FIFO8 *fifo,char *data,int len){
int i=0;
aos_mutex_lock(&(fifo->mutex),AOS_WAIT_FOREVER);
if(fifo->size!=fifo->free){
LOGD(TAG,"current fifo->getP =%d \n",fifo->getP);
for(i=0; ; i++){
*(data+i) =fifo->buf[fifo->getP++];
if(fifo->getP == fifo->size){//用来实现循环
fifo->getP = 0;
}
fifo->free++;
if(fifo->size==fifo->free){
LOGD(TAG,"the buffer is no data left!\n");
aos_mutex_unlock(&(fifo->mutex));
return i+1;
}
if(i+1==len){
LOGD(TAG,"read data finish!\n");
break;
}
}
}
else{
LOGI(TAG,"the buffer is empty!\n");
aos_mutex_unlock(&(fifo->mutex));
return 0;
}
aos_mutex_unlock(&(fifo->mutex));
return len;
}
/*缓冲区被使用容量*/
void fifo8_status(struct FIFO8 *fifo,int *used) {
aos_mutex_lock(&(fifo->mutex),AOS_WAIT_FOREVER);
*used = fifo->size - fifo->free;
aos_mutex_unlock(&(fifo->mutex));
}
/*缓冲区剩余容量*/
void fifo8_free(struct FIFO8 *fifo ,int *free) {
aos_mutex_lock(&(fifo->mutex),AOS_WAIT_FOREVER);
*free = fifo->free;
aos_mutex_unlock(&(fifo->mutex));
}
2、初始化缓冲区:fifo8_init(&_FIFO8,64);
3、向缓冲区压入数据:
fifo8_putPut(&_FIFO8,io_uart_para.vm_uart_rx_byte);//将接收的数据压入缓冲区
// io_uart_para.vm_uart_rx_buf[io_uart_para.vm_uart_rx_flag] = io_uart_para.vm_uart_rx_byte;
// io_uart_para.vm_uart_rx_flag = io_uart_para.vm_uart_rx_flag +1;
4、取出数据,输出到模拟串口:
while(1)
{
i = fifo8_get(&_FIFO8);
if(i == -1)
{
break;
}
else{
send_Char(i);
}
}
aos_msleep(1);
实验结果:还不是很理想,每200ms 发送一次,有丢包或者数据不对的方。可能接收的数据要做CRC,这样安全稳靠一些。
如果是一秒钟一次,是没问题,有精力再调一下,或者哪位高手帮忙看一下。
至此接串口模拟工程完一段落。下一辑,读取电流传感器。
|