缓冲区不能为空。 参数名: buffer_传感器前期编程_系统时间与环型缓冲区

3863193a4c67994894621473de51f1f9.png

来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)

作者:韦东山

本文字数:2091,阅读时长:2分钟

这节课实现两个小功能:系统时间环形缓冲区

在上一课的基础上添加代码,打开timer.c,前面的设置的定时器,每10ms产生一次中断,这里定义一个全局变量,来记录产生次数,

static unsigned int g_system_time_10ms_cnt = 0;

这里的类型选择使用unsigned int类型,2^32*10/1000/3600/24=497天,也就是说如果运行497天后,计数溢出,将会导致一些问题。

改为unsigned long long类型的话,2^64*10/1000/3600/24/365=5849424173年,这个时间就不怕溢出了,因此这里计数变量的类型为unsigned long long:

static unsigned long long g_system_time_10ms_cnt = 0;

在定时器中断timer_irq()函数里面让这个计数值每次加1:

g_system_time_10ms_cnt++;

以后我们就可以读取这个计数值,知道系统时间。

现在开始编写获取系统时间的函数,精度要求是us级别的,读取TCNTO0的值,再加上g_system_time_10ms_cnt的计数:

unsigned long long get_system_time_us(void){unsigned long long us = (50000 - TCNTO0)/5;return g_system_time_10ms_cnt * 10 * 1000 + us;}

通过这个函数就知道上电到之后任何一个时刻,过去了多久。

再写一个函数计算两段时间之间的差值:

unsigned int delta_time_us(unsigned long long pre, unsigned long long now){return (now - pre);}

到此,系统时间相关函数就完成了。

首先介绍一下环形缓冲区,假设有一个数组char Buf[6],它的结构如下:

d61bb52efe3d8d0b40b5f245a066f960.png

定义一个读指针r=0,一个写指针w=0。

  • 写数据:

buf[w] = val;

w = (w+1)%LEN = (w+1)%6;

  • 读数据:

val = buf(r);

r = (r+1)%LEN;

如何判断buf是空: r == w; //为空

如何判断buf是满: (w+1)%LEN == r; //为满

读写指针,每到达最后面,就从0开始,就像一个圆环一样,因此得名环形缓冲区。

对于我们红外数据,保存的数据并不是char,而是一个结构体,里面含有脉冲宽度,引脚极性等。

在sensors文件下创建一个irda文件夹,里面创建irda_raw.h和circle_buffer.c,在irda_raw.h里定义一个数据结构体,包含极性和脉冲宽度:

#ifndef _IRDA_RAW_H#define _IRDA_RAW_Htypedef struct irda_raw_event {int pol; /* 极性 */int duration;  /* 脉冲宽度, us */}irda_raw_event, *p_irda_raw_event;#endif /* _IRDA_RAW_H */

然后在circle_buffer.c实现环形缓冲区。

先定义个irda_raw_event类型的g_events[]数组,这里大小设置为1024,

之前介绍过,每传一次irda,至少会传67次数据,因此这个buf要至少大于67行,再定义两个读写指针位置。

static irda_raw_event g_events[1024];static int g_r = 0;static int g_w = 0;

判断buf是否是空的函数:

static int is_ir_event_buf_empty(void){return g_r = g_w;}

判断buf是否是满的函数:

static int is_ir_event_buf_full(void){return NEXT_PLACE(g_w) == g_r;}

其中,(w+1)%LEN使用宏NEXT_PLACE(i)代替,宏的定义如下:

#define NEXT_PLACE(i) ((i+1)&0x3FF)

%的操作使用位&操作实现一样的效果。

然后是把数据放入缓冲区:

int ir_event_put(p_irda_raw_event pd){if (is_ir_event_buf_full())return -1;g_events[g_w] = *pd;g_w = NEXT_PLACE(g_w);return 0;}

先判断的缓冲区是否已满,没满的话就在写的位置放入数据,然后写位置再移动到下一个。

最后是读数据:

int ir_event_get(p_irda_raw_event pd){if (is_ir_event_buf_empty())return -1;*pd = g_events[g_r];g_r = NEXT_PLACE(g_r);return 0;}

先判断的缓冲区是否是空,没空的话就在读的位置读出数据,然后读位置移到到下一个。

修改Makefile,添加本次写的新文件。

「新品首发」STM32MP157开发板火爆预售!首批仅300套

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值