飞思卡尔智能车之摄像头使用

   今天来给大家说说摄像头的使用,很显然摄像头对摄像头组的重要性是不言而喻的,因为摄像头是小车提取赛道信息最关键的传感器了,所以只有把摄像头使用好才能让你的小车快速稳定的跑起来。

   摄像头我选择的是数字摄像头,大家可以在某宝上购买。买来之后首先要做的就是给摄像头调焦,可以使用视频采集卡将摄像头与电脑连接,然后在电脑上看摄像头的图像调节摄像头焦距直至图像最清晰为止,摄像头和采集卡的连接很简单只要把摄像头的VTO和GND接口与采集卡的视频线接口连接好就OK,然后把视频卡插在电脑上安装好驱动和相应的软件即可,驱动和软件买采集卡的时候卖家会给。焦距调好后,我们要配置摄像头了,以实现摄像头的功能。配置摄像头也就是对摄像头内部芯片寄存器的配置,寄存器的具体配置要参考你所使用摄像头芯片的datesheet,寄存器的配置就和配置单片机寄存器一样的,不同寄存器的不同数值代表着摄像头的不同功能。不过这个配置是需要和单片机进行通信的,通过单片机给摄像头的寄存器写入数值,通信协议一般是用IIC通信。不懂IIC协议的同学可以去学习下,单片机没有IIC接口的,就得通过IO端口软件模拟出时序来通信了,不过也不难就是按照它协议规定的时序读写数据就行了。通过配置寄存器实现摄像头的数字量输出,也可以配置摄像头的分辨率和对比度,或者曝光率(这个曝光率可能只是调节它的上下限范围,拍摄时摄像头根据环境自动调整,我用的就是)。

下面是我软件模拟IIC的程序,供大家参考

/*-----------------------------------------------------------------------
delay_1ns         : 延时程序
编写日期          :2014-12-15
最后修改日期      :2014-12-15
-----------------------------------------------------------------------*/void BFDly_ms(uint8_t ms)
{volatile uint16_t ii,jj;if (ms<1) ms=1;for(ii=0;ii<ms;ii++)//  for(jj=0;jj<1335;jj++);     //16MHz--1msfor(jj=0;jj<3400;jj++);    //48MHz--1ms  //for(jj=0;jj<5341;jj++);    //64MHz--1ms  //  for(jj=0;jj<18200;jj++);     //200MHz--1ms
} /*-----------------------------------------------------------------------
BFdelay_1us         : 延时程序
编写日期          :2014-12-15
最后修改日期      :2014-12-15
-----------------------------------------------------------------------*/void BFdelay_1us(uint8_t us)                 //1us延时函数{volatile uint8_t i ;for(i=0;i<us;i++) {     }}//--------------------------------------------------------------------------------------------------
// 函数名称: iic_start()
// 函数功能: 启动I2C总线子程序
//--------------------------------------------------------------------------------------------------
void iic_start(void)
{   BFSDA = 1;  BFdelay_1us(1);      // 延时1us BFCLK = 1;BFdelay_1us(1);      // 延时5us BFSDA = 0;BFdelay_1us(1);  BFCLK = 0;BFdelay_1us(2);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: iic_stop()
// 函数功能: 停止I2C总线数据传送子程序
//--------------------------------------------------------------------------------------------------
void iic_stop(void)
{ BFSDA = 0;          //时钟保持高,数据线从低到高一次跳变,I2C通信停止BFdelay_1us(1);      // 延时1us BFCLK = 1;BFdelay_1us(1);BFSDA = 1;BFdelay_1us(1);BFCLK = 0;BFdelay_1us(2);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_ACK
// 函数功能: 从机发送应答位子程序
//--------------------------------------------------------------------------------------------------
void slave_ACK(void)
{BFSDA = 0; BFdelay_1us(1);      // 延时1us BFCLK = 1;BFdelay_1us(1);           BFSDA = 1;BFdelay_1us(1);      // 延时1us BFCLK = 0;BFdelay_1us(2);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_NOACK
// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
void slave_NOACK(void)
{ BFSDA = 1;  BFdelay_1us(1);      // 延时1us BFCLK = 1;BFdelay_1us(3);BFSDA = 0;BFdelay_1us(1);      // 延时1us BFCLK = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
uint8_t check_ACK(void)
{ uint8_t check ;BFSDA = 1; BFDDRA = 0 ;ATD0DIEN =ATD0DIEN|0x40;BFSDA = 1 ;BFdelay_1us(1);      // 延时1us BFCLK = 1;check = 0;if(BFSDA == 1)    // 若BFSDA=1 表明非应答,置位非应答标志F0check = 1;BFdelay_1us(1);      // 延时1us BFCLK = 0;BFDDRA = 1 ;         //BFSDA = 0 ;return  check ;
}//--------------------------------------------------------------------------------------------------
// 函数名称: IICSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
//--------------------------------------------------------------------------------------------------
void IICSendByte(uint8_t ch)
{ uint8_t n=8;     // 向BFSDA上发送一位数据字节,共八位while(n--){ if((ch&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1{BFSDA = 1;    // 传送位1BFdelay_1us(1);BFCLK = 1;BFdelay_1us(2);BFCLK = 0;  BFdelay_1us(1);BFSDA = 0;BFdelay_1us(1);}else{  BFSDA = 0;    // 否则传送位0BFdelay_1us(1);BFCLK = 1;BFdelay_1us(2);BFCLK = 0;  BFdelay_1us(2);}ch = ch<<1;    // 数据左移一位}
}
//--------------------------------------------------------------------------------------------------
// 函数名称: IICreceiveByte
// 返回接收的数据
// 函数功能: 接收一字节子程序
//--------------------------------------------------------------------------------------------------
uint8_t IICreceiveByte(void)
{uint8_t n=8;    // 从BFSDA线上读取一上数据字节,共八位uint8_t tdata = 0;while(n--){      BFDDRA = 0 ;ATD0DIEN =ATD0DIEN|0x40;BFSDA = 1;BFdelay_1us(1);BFCLK=0;BFdelay_1us(2);BFCLK = 1;BFdelay_1us(2);tdata = tdata<<1;    // 左移一位,或_crol_(temp,1)if(BFSDA == 1)tdata = tdata|0x01;    // 若接收到的位为1,则数据的最后一位置1else tdata = tdata&0xfe;    // 否则数据的最后一位置0BFCLK=0;BFDDRA = 1 ;}return(tdata);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: writeNbyte
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//--------------------------------------------------------------------------------------------------
uint8_t writeNbyte(uint8_t slave_add, uint8_t *slave_data,uint16_t n)
{          uint8_t send_da,check = 1;uint16_t i=0;uint8_t *Send_databuff ;Send_databuff = slave_data ;//  uart_putchar(UART0,slave_data[0]);//   uart_putchar(UART0,n>>8);iic_start();                // 启动I2CIICSendByte(slave_add);     // 发送地址位check = check_ACK();                // 检查应答位//   SCI0_SendChar1(check);if(check == 1){ return IICEorr;    // 若非应答表明器件错误或已坏,置错误标志位SystemError}while(n--){ send_da = Send_databuff[i++];  IICSendByte(send_da);     check= check_ACK();    // 检查应答位//uart_putchar(UART0,send_da);if (check == 1){return IICEorr;    // 若非应答表明器件错误或已坏,置错误标志位SystemError}}iic_stop();         // 全部发完则停止return IICOK;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: receiveNbyte
// 入口参数: slave_add从机地址,n要接收的数据个数
// 函数功能: 接收n位数据子程序
//--------------------------------------------------------------------------------------------------
uint8_t receiveNbyte(uint8_t slave_add,uint8_t *rece_data, uint16_t n)
{ uint8_t receive_da,check;uint16_t i=1;uint8_t *rece_data_buff ;rece_data_buff = rece_data ;iic_start();IICSendByte(0XDC);BFdelay_1us(1);      // 延时1us check =check_ACK();if(check == 1){return IICEorr ;}IICSendByte(rece_data_buff[0]);BFdelay_1us(1);      // 延时1us check =check_ACK();if(check == 1){return IICEorr ;}// uart_putchar(UART0,rece_data_buff[0]);iic_start();IICSendByte(slave_add);BFdelay_1us(1);      // 延时1us check =check_ACK();if(check == 1){return IICEorr ;}for(;n > 1;n--){ receive_da=IICreceiveByte();rece_data_buff[i++]=receive_da;slave_ACK();    // 收到一个字节后发送一个应答位//       uart_putchar(UART0,receive_da);}receive_da=IICreceiveByte();rece_data_buff[i++]=receive_da;slave_NOACK();    // 收到最后一个字节后发送一个非应答位//   uart_putchar(UART0,receive_da);iic_stop();return IICOK;}//--------------------------------------------------------------------------------------------------
// 函数名称: IICWriteGpio_inint
// 入口参数:
// 函数功能:
//--------------------------------------------------------------------------------------------------
void IICWriteGpio_inint(void)
{DDR1AD0 |= 0X60 ;PT1AD0_PT1AD06 =1 ; PT1AD0_PT1AD05 =1 ;
}

   摄像头寄存器的配置搞定的话就可以编写摄像头采集数据的时序程序了,这个需严格根据摄像头的场中断和行中断的时序来编写,否则时序乱了就会导致摄像头采集到消隐区的数据都是无效的数据,我也给大家看过那个时序图,大家得看懂那个时序图,这样编写程序才不会出错。我的采集思路是在摄像头的一帧图像中利用行中断来采集数据,消隐区的时间来处理数据。

采集数据时序程序如下,本人用的单片机是XS128,大家自己研究研究

/*********************************************************
/***************  图像采样中断服务子函数  ************************************************************************/#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 24 PTJ6_inter(void)
{if(HREF_max%4==0){  Data[HREF_counter][0] = PORTA; _asm(nop);Data[HREF_counter][1] = PORTA; Data[HREF_counter][2] = PORTA; _asm(nop);Data[HREF_counter][3] = PORTA; Data[HREF_counter][4] = PORTA; _asm(nop);Data[HREF_counter][5] = PORTA;Data[HREF_counter][6] = PORTA;Data[HREF_counter][7] = PORTA;  Data[HREF_counter][8] = PORTA; Data[HREF_counter][9] = PORTA; Data[HREF_counter][10] = PORTA;Data[HREF_counter][11] = PORTA; Data[HREF_counter][12] = PORTA;Data[HREF_counter][13] = PORTA;Data[HREF_counter][14] = PORTA;Data[HREF_counter][15] = PORTA;Data[HREF_counter][16] = PORTA;Data[HREF_counter][17] = PORTA;Data[HREF_counter][18] = PORTA;Data[HREF_counter][19] = PORTA;Data[HREF_counter][20] = PORTA;Data[HREF_counter][21] = PORTA;Data[HREF_counter][22] = PORTA;Data[HREF_counter][23] = PORTA;Data[HREF_counter][24] = PORTA;Data[HREF_counter][25] = PORTA;Data[HREF_counter][26] = PORTA;Data[HREF_counter][27] = PORTA;Data[HREF_counter][28] = PORTA;Data[HREF_counter][29] = PORTA;Data[HREF_counter][30] = PORTA;Data[HREF_counter][31] = PORTA; Data[HREF_counter][32] = PORTA; Data[HREF_counter][33] = PORTA;Data[HREF_counter][34] = PORTA; Data[HREF_counter][35] = PORTA; Data[HREF_counter][36] = PORTA;Data[HREF_counter][37] = PORTA;Data[HREF_counter][38] = PORTA;Data[HREF_counter][39] = PORTA;Data[HREF_counter][40] = PORTA;Data[HREF_counter][41] = PORTA;Data[HREF_counter][42] = PORTA;Data[HREF_counter][43] = PORTA; Data[HREF_counter][44] = PORTA;Data[HREF_counter][45] = PORTA;Data[HREF_counter][46] = PORTA;Data[HREF_counter][47] = PORTA;Data[HREF_counter][48] = PORTA;Data[HREF_counter][49] = PORTA;Data[HREF_counter][50] = PORTA;Data[HREF_counter][51] = PORTA; Data[HREF_counter][52] = PORTA;Data[HREF_counter][53] = PORTA; Data[HREF_counter][54] = PORTA;Data[HREF_counter][55] = PORTA; Data[HREF_counter][56] = PORTA;Data[HREF_counter][57] = PORTA; Data[HREF_counter][58] = PORTA;Data[HREF_counter][59] = PORTA; Data[HREF_counter][60] = PORTA;Data[HREF_counter][61] = PORTA; Data[HREF_counter][62] = PORTA;Data[HREF_counter][63] = PORTA; Data[HREF_counter][64] = PORTA;Data[HREF_counter][65] = PORTA;Data[HREF_counter][66] = PORTA;Data[HREF_counter][67] = PORTA; Data[HREF_counter][68] = PORTA;Data[HREF_counter][69] = PORTA; Data[HREF_counter][70] = PORTA;Data[HREF_counter][71] = PORTA; Data[HREF_counter][72] = PORTA; Data[HREF_counter][73] = PORTA;  Data[HREF_counter][74] = PORTA;Data[HREF_counter][75] = PORTA;  Data[HREF_counter][76] = PORTA;Data[HREF_counter][77] = PORTA;  Data[HREF_counter][78] = PORTA;Data[HREF_counter][79] = PORTA;   Data[HREF_counter][80] = PORTA;Data[HREF_counter][81] = PORTA;Data[HREF_counter][82] = PORTA;Data[HREF_counter][83] = PORTA;Data[HREF_counter][84] = PORTA;Data[HREF_counter][85] = PORTA;Data[HREF_counter][86] = PORTA;Data[HREF_counter][87] = PORTA;Data[HREF_counter][88] = PORTA;Data[HREF_counter][89] = PORTA;Data[HREF_counter][90] = PORTA;Data[HREF_counter][91] = PORTA;Data[HREF_counter][92] = PORTA;Data[HREF_counter][93] = PORTA;Data[HREF_counter][94] = PORTA; Data[HREF_counter][95] = PORTA;Data[HREF_counter][96] = PORTA;Data[HREF_counter][97] = PORTA;Data[HREF_counter][98] = PORTA;Data[HREF_counter][99] = PORTA;Data[HREF_counter][100] = PORTA;Data[HREF_counter][101] = PORTA;Data[HREF_counter][102] = PORTA;Data[HREF_counter][103] = PORTA;Data[HREF_counter][104] = PORTA;Data[HREF_counter][105] = PORTA;Data[HREF_counter][106] = PORTA;Data[HREF_counter][107] = PORTA;Data[HREF_counter][108] = PORTA;Data[HREF_counter][109] = PORTA;Data[HREF_counter][110] = PORTA; Data[HREF_counter][111] = PORTA;Data[HREF_counter][112] = PORTA; Data[HREF_counter][113] = PORTA;Data[HREF_counter][114] = PORTA; Data[HREF_counter][115] = PORTA;Data[HREF_counter][116] = PORTA;Data[HREF_counter][117] = PORTA;Data[HREF_counter][118] = PORTA; Data[HREF_counter][119] = PORTA;PIFJ = PIFJ|0x40;     //清除行中断标志 HREF_counter++;HREF_max++;}else{PIFJ = PIFJ|0x40;     //清除行中断标志  HREF_max++; }if(HREF_counter==Line_max){PIEJ_PIEJ6=0 ;  //禁止行中断(PJ6)HREF_counter=0;HREF_max=0;ccd_data_deal_end_flags=1;}}#pragma CODE_SEG DEFAULT
<strong><span style="font-family:FangSong_GB2312;font-size:18px;color:#663300;background-color: rgb(102, 255, 255);">主函数里通过场信号的高低电平变化来判断一场是否结束</span></strong> 
void main()          <pre class="objc" name="code">     {      while(1){    while(VREF);while(!VREF);PIFJ_PIFJ6=1;    //清行中断标志PIEJ_PIEJ6=1;    //PJ6允许中断,即行中断允许,进行视频数据采集  while(!ccd_data_deal_end_flags);  //等待视频数据采集结束ccd_data_deal_end_flags=0;
                Led_flag=1;
            }
     }
<strong><span style="font-family:FangSong_GB2312;font-size:18px;color:#663300;background-color: rgb(102, 255, 255);">如果按照正确的时序采集数据的话基本上是没问题了,大家可以通过调试软件查看采集到的数据,观察是否为有效数据,一般黑色的灰度值小于100,白色灰度值为200左右,这样的数据就是正常的,有个别数据异常那可能是噪点,程序上就要通过滤波来滤除这些噪点,滤波有很多方法以后会给大家介绍。以上采集数据的方法仅是我个人方法,大家也可以自己根据时序想出更好的方法来,当然肯定有更好的方法的,大家可以在网上找找资料,比如可以开辟出双数组,一个用来采集数据用,另一个用来处理数据用,这样效率更高。</span></strong>

飞思卡尔智能车之摄像头使用篇相关推荐

  1. 飞思卡尔智能车摄像头上位机…

    原文地址:飞思卡尔智能车摄像头上位机采集程序 作者:玲声依旧美 基于飞思卡尔XS128单片机 摄像头采集测试程序     OV7620采集程序说明:摄像头数据口接PA0-PA7:行中断接PT0,场中断 ...

  2. ai电磁组属于什么组_飞思卡尔智能车电磁组分区算法介绍

    写在之前的话: 1.目前我是一名在校学生,这也是我第一次写博客,不周之处,请多谅解: 2.此算法并非原创,借鉴自山东德州学院第八届白杨队(PS:个人看法,对于一些人把别人的开源东西改头换面一下就说是自 ...

  3. 第五届“飞思卡尔”智能车竞赛分赛区赛后总结

    两天紧张的比赛结束了,第五届"飞思卡尔"智能车竞赛安徽省分赛区的全部比赛也到此结束了.在黄山,我体验了黄山风景的美丽,也体会了各院校在"飞思卡尔"项目上的强大. ...

  4. 最小二乘法在飞思卡尔智能车路径搜索中的应用

    1.什么是最小二乘法 最小二乘法就是要使得观测点和估计点的距离的平方达到最小,我们可以使用一些已知的离散的点,拟合出一条与这些离散点最为接近的曲线,从而可以分析出这些离散点的走向趋势. 如图所示是一个 ...

  5. 飞思卡尔智能车—无线充电电源(节能组)

    飞思卡尔智能车-无线充电电源(节能组) 详细参赛要求请以智能车官方为准,此文章仅分享本人参赛经验,开源硬件电路设计,供大家学习! 无线充电部分设计思路: 无线充电接收线圈,超级电容充电,启动电压5V, ...

  6. 红外寻迹小车基于K128单片机的红外对管飞思卡尔智能车(5个对管)程序部分

    红外寻迹小车基于K128单片机的红外对管飞思卡尔智能车(5个对管)软件部分包括: 出库 直行模块 大,小弯道 环岛 s弯 停车 #include "headfile.h" #inc ...

  7. 飞思卡尔智能车—电磁循迹(节能组)

    飞思卡尔智能车-电磁循迹(节能组) 详细参赛要求请以智能车官方为准,此文章仅分享本人参赛经验,开源硬件电路设计,供大家学习! 电磁循迹部分设计思路: 电感采集电磁信号,放大,整流,滤波,AD采集 电磁 ...

  8. 回忆属于我的第五届“飞思卡尔”智能车竞赛

    飞思卡尔,一个原本陌生,而现在常常挂在嘴边的名字-- 09年高考的结束,注定了我只能来到芜湖职业技术学院这个专科,当时的心情很失落,其实无论拿哪次模拟考的成绩,我都是可以上个二本的,郁闷了-- 因为自 ...

  9. 智能车改舵机中值步骤_飞思卡尔智能车摄像头组新手指南(10)--控制算法进阶篇之舵机3...

    曲率 彭岸辉 从理论上讲,相对于偏差量,曲率是智能车更好的一个控制变量.但由于路径检测单元的局限性,很难计算出非常精确的曲率. 注意:计算曲率的方法如果要提高精度,最好是能够将采到的畸形图像做一下校正 ...

最新文章

  1. 爬虫之switch_to切换frame标签
  2. 一种医学图像分割的新思路【nnU-Net网络配置教程】
  3. JavaScript——易班优课YOOC课群在线测试禁止右键和复制解决方案
  4. Windows服务二:测试新建的服务、调试Windows服务
  5. ZABBIX2.4.8监控 Windows Mysql数据库
  6. Java 流式编程stream
  7. word无法打开请去应用商店_word软件是什么?word文档是什么?可以用来干什么?...
  8. python sphinx_Python Sphinx使用实例及问题解决
  9. 算gini 随机森林_随机森林
  10. Nginx学习总结(6)——Nginx + https + 免费SSL证书配置指南
  11. Chem 3D模型的参数值更改方法
  12. cocos2dx 字体外发光_Cocos2d-x 3.x开发塔防游戏《王国保卫战》02:地图(一)
  13. Python 进阶 — Flake8 静态代码检查工具
  14. 网络中的IP地址(包括私网地址)
  15. 《都挺好》一部黑码农的神剧!
  16. leetcode刷题目录总结
  17. python爬虫 - 代理ip正确使用方法
  18. java 单位转换的程序_Java 实现长度单位换算
  19. 深入理解iputils网络工具-第5篇 arping:地址解析程序
  20. 实验A---- ADFA的可判定性

热门文章

  1. 格式化数据方法 sanitize
  2. 计算机虚拟现实主要学什么,虚拟现实计算机教学应用
  3. 第6关:人民币美元汇率双向兑换计算
  4. java输出各种图案_Java打印各种小图形,各种三角形、菱形
  5. Shader-FresnelReflection(菲涅尔反射)
  6. 戴文的Linux内核专题:03 驱动程序【转】
  7. 线性表的顺序存储及运算的实现
  8. Cache数据库ECP梳理
  9. ARMv8通用定时器简介
  10. 【Python】成功解决 str object has no attribute decode