主页 > 互联网 > 内容页

全球新动态:基于Linux设计的倒车雷达系统

2023-05-25 09:02:46 来源:DS小龙哥-嵌入式技术


【资料图】

一、项目背景介绍

随着社会的不断发展,人们对于汽车的安全性要求越来越高,而倒车雷达系统就是为了增强汽车驾驶者的安全性而被广泛使用。在这种情况下,我们开发了一个基于Linux设计的倒车雷达系统,该系统可以采用迅为4412主控板,运行Linux3.5内核,使用USB摄像头、TFT真彩显示屏、超声波测距模块和蜂鸣器等硬件

二、创新点

本项目的创新点包括:

采用开源Linux系统:采用Linux系统,具有很好的可扩展性和灵活性,可以实现更为丰富和复杂的功能。多个模块的协同工作:本项目涉及到了摄像头模块、超声波测距模块、处理模块、告警模块和显示模块等多个模块,这些模块需要协同工作才能实现完整的功能。实现了告警功能:本项目采用了蜂鸣器来实现告警功能,根据距离调整PWM输出给出不同级别的告警声音,能够提醒驾驶者注意障碍物。

三、使用技术介绍

迅为4412主控板:本项目采用了迅为4412主控板,该主控板具有较高的性能和稳定性,能够满足系统的运行要求。Linux操作系统:本项目采用了开源的Linux操作系统,具有很好的可扩展性和灵活性,适合进行自定义开发。V4L2协议:V4L2协议是Linux下的一个视频设备驱动程序接口,可以方便地实现USB摄像头的图像采集。超声波测距模块:通过GPIO口与主控板相连,使用定时器产生超声波并计算与接收到回波之间的时间差,从而计算出与障碍物之间的距离。PWM输出控制:根据距离调整PWM输出给出不同级别的告警声音。TFT真彩显示屏:本项目采用了TFT真彩显示屏,能够实现高清晰度的图像显示。系统管理模块:负责管理整个系统的启动、配置和错误处理等操作。例如,可以将系统的启动脚本写在/etc/rc.local中,通过调用shell脚本来实现系统的初始化和启动。

四、系统架构

整个系统由以下几个模块组成:

摄像头模块:负责采集车尾环境图像,并传输给处理模块。超声波测距模块:负责与障碍物之间的距离测量,并将结果传输给处理模块。处理模块:负责视频显示、距离信息的处理、告警功能的实现。告警模块:负责根据距离调整PWM输出给出不同级别的告警声音,并使用蜂鸣器输出告警信息。显示模块:负责将处理模块生成的图像显示在TFT真彩显示屏上。系统管理模块:负责管理整个系统的启动、配置和错误处理等操作。

五、功能设计

摄像头模块 由于Linux系统具有很好的驱动支持,因此可以直接使用V4L2协议来获取USB摄像头的图像。获取图像后,需要通过DMA方式将数据传输给处理模块进行处理。超声波测距模块 超声波测距模块可以通过GPIO口与主控板相连,使用定时器产生超声波并计算与接收到回波之间的时间差,从而计算出与障碍物之间的距离。处理模块 处理模块负责将摄像头采集到的图像和超声波测距模块测得的距离信息整合处理,并根据距离信息来控制告警模块。告警模块 告警模块根据处理模块传递过来的距离信息来控制PWM输出,并使用蜂鸣器输出告警信息。显示模块 显示模块负责将处理模块生成的图像显示在TFT真彩显示屏上,并实现显示屏的刷新和管理操作。系统管理模块 系统管理模块负责管理整个系统的启动、配置和错误处理等操作。例如,可以将系统的启动脚本写在/etc/rc.local中,通过调用shell脚本来实现系统的初始化和启动。

六、摄像头图像显示应用代码

#include  #include           /* See NOTES */ #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include   #include  ​ /* 图片的象素数据 */ typedef struct PixelDatas {     int iWidth;      /* 宽度: 一行有多少个象素 */     int iHeight;     /* 高度: 一列有多少个象素 */     int iBpp;        /* 一个象素用多少位来表示 */     int iLineBytes;  /* 一行数据有多少字节 */     int iTotalBytes; /* 所有字节数 */      unsigned char *VideoBuf; //存放一帧摄像头的数据     //指向了存放摄像头数据的空间地址 }T_PixelDatas; ​ T_PixelDatas Pixedata; //存放实际的图像数据 ​ /*         USB摄像头相关参数定义 */ struct v4l2_buffer tV4l2Buf; int iFd; int ListNum; unsigned char* pucVideBuf[4];  // 视频BUFF空间地址 void camera_pthread(void); ​ //LCD屏相关的参数 unsigned char *lcd_mem=NULL; /*LCD的内存地址*/ struct fb_fix_screeninfo finfo; /*固定形参*/ struct fb_var_screeninfo vinfo; /*可变形参*/ void LCD_Init(void); void show_pixel(int x,int y,int color); ​ ​ int main(int argc ,char *argv[]) {     if(argc!=2)     {         printf("./app /dev/videoX");         return -1;     }          LCD_Init(); //LCD屏初始化          camera_init(argv[1]);  //摄像头设备初始化          //开始采集摄像头数据,并实时显示在LCD屏幕上     camera_pthread();     return 0; } ​ ​ ​ //LCD屏初始化 void LCD_Init(void) {     /*1.打开设备文件*/     int fd=open("/dev/fb0",O_RDWR);     if(fd<0)     {         printf("/dev/fb0设备文件打开失败!");         return;     }          /*2. 读取LCD屏的参数*/     ioctl(fd,FBIOGET_FSCREENINFO,&finfo);//固定参数     printf("映射的长度:%d",finfo.smem_len);          ioctl(fd,FBIOGET_VSCREENINFO,&vinfo);//可变参数,32位     printf("分辨率:%d*%d,%d",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel); ​     /*3. 映射LCD的地址到进程空间*/     lcd_mem=mmap(NULL,finfo.smem_len,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);     if(lcd_mem==NULL)     {         printf("lcd_mem映射失败!");         return;     }     memset(lcd_mem,0xFFFFFFFF,finfo.smem_len); } ​ /*画点*/ void show_pixel(int x,int y,int color) {     unsigned long *show32 = NULL;     /* 定位到 LCD 屏上的位置*/     show32 =(unsigned long *)(lcd_mem + y*vinfo.xres*vinfo.bits_per_pixel/8 + x*vinfo.bits_per_pixel/8);     *show32 =color; /*向指向的 LCD 地址赋数据*/ } ​ ​ //显示摄像头的数据 void Show_VideoData(int w,int h,unsigned char *rgb) {     int i,j;     int x0,x=0,y=0;     int color; //颜色 值     unsigned char r,g,b;     x0=x;     for(i=0;i

七、超声波测距驱动代码

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  ​ #include  #include  #include  ​ #include  ​ static int chaoshengbo_irq=0; ​ #define GPB_CON  0x11400040 #define GPB_DAT  0x11400044 ​ static u32 *gpb_con=NULL; static u32 *gpb_dat=NULL; ​ /* 硬件连接: 输出脚: GPX1_0 ---ECHO 输入脚: GPB_7  */ static void tiny4412_work_func(struct work_struct *work) {        printk("GPB=%d",*gpb_dat&1<<7); ​     ktime_t my_time1,my_time2;     unsigned int i,j;     unsigned int time_cnt=0; ​     my_time1=ktime_get();  //获取当前时间     i=ktime_to_us(my_time1); //转 us ​     while(gpio_get_value(EXYNOS4_GPX1(0))){} //高电平卡住 ​          my_time2=ktime_get(); //获取当前时间     j=ktime_to_us(my_time2); //转 us ​     printk("us:%d",j-i); } ​ static DECLARE_WORK(caoshengbotiny4412_work,tiny4412_work_func); ​ /* 中断处理函数 */ irqreturn_t irq_handler_chaoshengbo(int irq, void *dev) {     schedule_work(&caoshengbotiny4412_work); /*正常情况下:  是在中断服务函数里面*/     return IRQ_HANDLED; /*表示中断已经处理过了*/ } ​ static void timer_function(unsigned long data); static DEFINE_TIMER(timer_caoshengbo, timer_function,0,0); ​ static void timer_function(unsigned long data) {     static u8 state;     state=!state;          if(state)*gpb_dat|=1<<7;     else *gpb_dat&=~(1<<7);      ​     mod_timer(&timer_caoshengbo,jiffies+msecs_to_jiffies(500));  } ​ static int __init tiny4412_chaoshengbo_init(void) {     int i,err;     /*获取中断号*/     chaoshengbo_irq=gpio_to_irq(EXYNOS4_GPX1(0));     printk("中断号:%d",chaoshengbo_irq);          /*外部中断注册*/     err=request_irq(chaoshengbo_irq,irq_handler_chaoshengbo,IRQ_TYPE_EDGE_RISING,"tiny4412_chaoshengbo",NULL);     if(err!=0)printk("中断注册失败!"); ​     /*映射内存*/     gpb_con=ioremap(GPB_CON,4);     gpb_dat=ioremap(GPB_DAT,4); ​     /*配置模式*/     *gpb_con&=~(0xF<<4*7); //输出模式        *gpb_con|=0x1<<4*7;          mod_timer(&timer_caoshengbo,jiffies+msecs_to_jiffies(100));              return 0; } ​ static void __exit tiny4412_chaoshengbo_exit(void) {     free_irq(chaoshengbo_irq,NULL);     iounmap(gpb_con);     iounmap(gpb_dat);     del_timer(&timer_caoshengbo); } ​ module_init(tiny4412_chaoshengbo_init);  /*指定驱动的入口函数*/ module_exit(tiny4412_chaoshengbo_exit);  /*指定驱动的出口函数*/ MODULE_LICENSE("GPL");      /*指定驱动许可证*/ ​ ​

标签:

上一篇:二极管检波电路结构和工作原理_当前速递
下一篇:最后一页