Linux小项目-倒车影像功能设计

1. 前言 倒车影像已经是现在汽车的标配功能了,基本很多车出厂都是360全景影像,倒车影像又称泊车辅助系统,这篇文章就采用linux开发板完成一个倒车影像的功能。
要完成倒车影像整个项目,需要准备一个lcd屏,一个摄像头,一个超声波测距模块,一个蜂鸣器;摄像头采集车尾的实时画面,在lcd屏上完成显示,超声波测距模块用于测量车尾距离障碍物的距离,根据设置的距离跳转pwm操作蜂鸣器实现报警提示。
当前linux开发板采用友善之臂的tiny4412开发板,cpu是三星的exynos4412,板子上带有8g的emmc,2g的drr,运行的linux版本是3.5,根文件系统采用busybox制作,这个系统是精简的最小系统。
摄像头采用usb免驱是摄像头,所有不需要编写驱动,lcd屏是友善之臂自己的7寸电容触摸屏,驱动是官方内核自带的,也不需要编写;剩下的超声波模块,蜂鸣器,需要自己填写驱动。
2. 案例代码 下面就将倒车影像项目的整个项目核心代码依次展示出来。
2.1 声波测距模块 采用的超声波模块在淘宝上很容易买到,它的实物图和测距原理如下:
整个模块只需要接4根线,两根电源线,一个输出触发脚,一个回波输出脚。输出脚是高电平有效,为了方便计算时间,驱动代码里需要将这个引脚注册为中断,设置为上升沿触发,当收到回波时,直接进中断调用工作队列,在工作函数里阻塞等待引脚电平变低,然后高电平持续的计算时间,最后进行换算就得到了距离。
驱动代码如下:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static unsigned int distance_irq; /*存放中断号*/static u32 *gpb_dat=null;static u32 *gpb_con=null;static u32 distance_time_us=0; /*表示距离的时间*/static u8 distance_flag=0;/*声明等待队列头*/static declare_wait_queue_head(distance_wait_queue);/*工作队列处理函数: */static void distance_work_func(struct work_struct *work){ u32 time1,time2; time1=ktime_to_us(ktime_get()); /*获取当前时间,再转换为 us 单位*/ /*等待高电平时间结束*/ while(gpio_get_value(exynos4_gpx1(0))){} time2=ktime_to_us(ktime_get()); /*获取当前时间,再转换为 us 单位*/ distance_flag=1; distance_time_us=time2-time1; /*唤醒休眠的进程*/ wake_up(&distance_wait_queue); //printk(us=%d\n,time2-time1); /*us/58=厘米*/}/*静态方式初始化工作队列*/static declare_work(distance_work,distance_work_func);/*中断处理函数: 用于检测超声波测距的回波*/static irqreturn_t distance_handler(int irq, void *dev){ /*调度工作队列*/ schedule_work(&distance_work); return irq_handled;}static void distance_function(unsigned long data);/*静态方式定义内核定时器*/static define_timer(distance_timer,distance_function,0,0);/*内核定时器超时处理函数: 触发超声波发送方波*/static void distance_function(unsigned long data){ static u8 state=0; state=!state; /*更改gpio口电平*/ if(state) { *gpb_dat|=1<<7; } else { *gpb_dat&=~(1<<7); } /*修改定时器的超时时间*/ mod_timer(&distance_timer,jiffies+msecs_to_jiffies(100));}static int distance_open(struct inode *inode, struct file *file){ return 0;}#define get_us_time 0x45612static long distance_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long argv){ u32 *us_data=(u32*)argv; int err; u32 time_us=distance_time_us; switch(cmd) { case get_us_time: err=copy_to_user(us_data,&time_us,4); if(err!=0)printk(拷贝失败!\n); break; } return 0;}static unsigned int distance_poll(struct file *file, struct poll_table_struct *table){ unsigned int mask = 0; poll_wait(file,&distance_wait_queue,table); if(distance_flag) { distance_flag=0; mask|=poll_in; } return mask;}static int distance_release(struct inode *inode, struct file *file){ return 0;}/*定义文件操作集合*/static struct file_operations distance_fops={ .open=distance_open, .unlocked_ioctl=distance_unlocked_ioctl, .poll=distance_poll, .release=distance_release};/*定义杂项设备结构体*/static struct miscdevice distance_misc={ .minor=misc_dynamic_minor, .name=tiny4412_distance, .fops=&distance_fops};static int __init tiny4412_distance_dev_init(void) { int err; /*1. 映射gpio口地址*/ gpb_dat=ioremap(0x11400044,4); gpb_con=ioremap(0x11400040,4); *gpb_con&=~(0xf<<4*7); *gpb_con|=0x1duty_ns = 0; ​  return 0; } ​ static int s3c_pwm_resume(struct platform_device *pdev) {  struct pwm_device *pwm = platform_get_drvdata(pdev);  unsigned long tcon; ​  /* restore invertion */  tcon = __raw_readl(s3c2410_tcon);  tcon |= pwm_tcon_invert(pwm);  __raw_writel(tcon, s3c2410_tcon); ​  return 0; } ​ static struct platform_driver s3c_pwm_driver = {  .driver = {  .name = s3c24xx-pwm,  .owner = this_module,  },  .probe = s3c_pwm_probe,  .remove = __devexit_p(s3c_pwm_remove),  .suspend = s3c_pwm_suspend,  .resume = s3c_pwm_resume, }; ​ static int __init pwm_init(void) {  int ret; ​  clk_scaler[0] = clk_get(null, pwm-scaler0);  clk_scaler[1] = clk_get(null, pwm-scaler1); ​  if (is_err(clk_scaler[0]) || is_err(clk_scaler[1])) {  printk(kern_err %s: failed to get scaler clocks\n, __func__);  return -einval;  } ​  ret = platform_driver_register(&s3c_pwm_driver);  if (ret)  printk(kern_err %s: failed to add pwm driver\n, __func__); ​  return ret; }复制代码 2.3 应用层框架代码 应用层使用了两个线程:
线程1实时读取usb摄像头的图像,在lcd屏上实时显示,免驱摄像头框架v4l2有一套标准的ioctl指令,可以对摄像头进行配置,比如:输出分辨率、帧率、格式等。然后再通过mmap映射摄像头采集缓冲区到应用层,最后通过poll函数监听摄像头的数据,读取实时显示。
线程2采集超声波测量的距离距离,根据测量的距离调整pwm占空比,控制蜂鸣器的频率。


iPhone12来了:全面支持5G,砍掉了耳机和充电器!
vivo X30 × 刘雯时尚大片首曝光,高级质感一跃而出
芯力特国产CAN FD芯片SIT1051,IO兼容3.3.V逻辑电平
关于韩公司研发织物OLED显示技术分析介绍
小米的电视品牌半年度出货量和销量突破400万!斩获第一!
Linux小项目-倒车影像功能设计
智能魔镜的功能有很多,不仅智能还会居家
区块链在电力行业中的应用场景探讨
小米游戏本性能怎么样
在选择物联网卡的时候要注意什么问题
数字显示的可调直流稳压电源设计
共享遛娃小车被清!共享单车被弃工地、共享马扎一天丢一半!深思共享经济是需求还是伪需求?
如获新生 3D打印帮猫咪接上仿生爪
90V三相栅极驱动芯片-PT5619
铝带拉力测试机:测试方法与应用领域
充分利用 FTP分类账户设置经验谈
关于比亚迪全新e平台功能介绍
暑期大促 买玄冰400抽荣耀50Pro手机
苹果AirTag有可能成为UWB市场爆发的导火索
面对海量数据的存储问题,去中心化分布式架构解决方案