网站首页 > 技术文章 正文
来源:百问网_嵌入式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],它的结构如下:
定义一个读指针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_H
typedef 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,添加本次写的新文件。
猜你喜欢
- 2024-09-20 非常详细!如何理解表格存储的多版本、生命周期和有效版本偏差
- 2024-09-20 6种快速统计代码执行时间的方法,真香
- 2024-09-20 Java 开发者最困惑的四件事(java开发遇到问题如何解决)
- 2024-09-20 【Java多线程】定时器Timer(java定时器线程池)
- 2024-09-20 还在用new Date计算任务执行时间?强烈建议使用这个API
- 2024-09-20 “抄”代码,再也不用上谷歌复制粘贴了
- 2024-09-20 java获取当前时间的四种方法代码实例
- 2024-09-20 撸完这篇线程池,我快咳血了(线程池有什么用)
- 2024-09-20 JAVA轮询遍历两个数组进行比较(遍历数组 java)
- 2024-09-20 蒙圈了?System.currentTimeMillis()存在性能问题
- 1514℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 563℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 508℃MySQL service启动脚本浅析(r12笔记第59天)
- 486℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 485℃启用MySQL查询缓存(mysql8.0查询缓存)
- 465℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 445℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 442℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)