[资料分享] 光流传感器的TM4C123GH6PM程序

@ai_pmz   2016-7-8 21:31 楼主
/*
*函数名: ADNS_3080_GPIO_Configuration(void)
*描述  :ADNS3080的使能引脚PTC5-NCS  掉电PC6-NPD=0  复位引脚PC7-RST 的初始化
*输入  :无
*输出  :无
*调用  :内部调用
*/
void ADNS_3080_GPIO_Configuration(void)
{
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);                              //使能PTC
        GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5); //PTC5-NCS芯片使能引脚  PC6-NPD=0 芯片掉电 PC7-RST 复位       
}
/*
*函数名: ADNS3080_reset(void)
*描述  :ADNS3080 复位脉冲信号
*输入  :无
*输出  :无
*调用  :内部调用
*/
void ADNS3080_reset(void)  //ADNS3080 复位(高)脉冲信号
{
        GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, 0x00);
        delayms(5);//5ms
        GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, 0x80);
        delayms(5);//5ms
        GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, 0x00);               
}

/*
*函数名: Write_srom(void)
*描述  :SROM下载函数 A3080的固件下载
*输入  :无
*输出  :无
*调用  :内部调用
*/
void Write_srom(void)
{
          
         int i;
         ON_CS();
         writr_register(0x20,0x44);                 //0x20-0x3C是保留出来的寄存器
         delayus(51 );
         writr_register(0x23,0x07);
         delayus(51);
         writr_register(0x24,0x88);
         delayus(51 );
         OFF_CS();                               //突发_写模式
         delayus(340);                          //等待大于1帧时间
         ON_CS();
         writr_register(SROM_Enable,0x18);     //下载SROM固件到SROM_Load寄存器之前要将0X18写入该寄存器
         OFF_CS();                            //突发_写模式
         delayus(41);                         //  >40us
         ON_CS();
         for(i=0;i<=1985;i++)
          {
                  writr_register(0x60,SROM[i]);   //0x60 下载静态只读存储器 寄存器  SROM_Load寄存器是被用于高速编程3080的一个外部SROM或单片机。
                  delayus(11);// >10us
          }
         OFF_CS();
         delayus(105);        //>104us
            
}
/*
*函数名: ADNS3080_Init(void)
*描述  :A3080的初始化
*输入  :无
*输出  :无
*调用  :主函数调用
*/
void ADNS3080_Init(void)
{          
          ADNS_3080_GPIO_Configuration();
          SPI_TM4C123_init();  
          ADNS3080_reset();                                 //复位PC7
          GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6, 0x40);  //拉高NPD,免睡眠
          delayms(10);
          Write_srom();                                    //写SROM_enable寄存器 下载固件
          delayms(100);
          ADNS_Configuration();
}
/*
*函数名: ADNS_Configuration(void)
*描述  :A3080的寄存器配置
*输入  :无
*输出  :无
*调用  :主函数调用
*/
void ADNS_Configuration(void)
{
         ON_CS();
         writr_register(Configuration_bits,0x10);                           //设置分辨率 1600  0x10         //若Bit 4为0 即0X00,则为400点每英寸
         delayms(3);
         writr_register(Extended_Config,0x01);                     //固定帧速率 由Frame_Period_Max_Bound 寄存器里的值决定
         delayms(3);
         if(read_busy()!=1)                                       //帧率的判忙 Extended_Config寄存器最高位dusy ==1忙 ==0允许写  
         {                                                                                   //设为3000帧每秒
                 OFF_CS();                                           //突发_写模式
                 delayms(2);
                 ON_CS();       
                SPI_SendReceive(Frame_Period_Max_Bound_Lower+0x80);        //设置帧率 //先写低位再写高位
                SPI_SendReceive(0x40);                              // 帧率=时钟频率/寄存器的值
                SPI_SendReceive(Frame_Period_Max_Bound_Upper+0x80);
                SPI_SendReceive(0x1f);                                   // 0x1f40=8000   

//                 writr_register(Frame_Period_Max_Bound_Lower,0x40);   //设置帧率 //先写低位再写高位  帧率=时钟频率/寄存器的值
//                  writr_register(Frame_Period_Max_Bound_Upper,0x1f);   //帧率=时钟频率/寄存器的值 =76000000/8000=9500Hz=0.1ms
         }
         clear_motion();                                         //运动寄存器清零   编写任何值这个寄存器将导致Delta_X,Delta_Y和内部运动寄存器被清除。
         OFF_CS();
}
/*
*函数名: read_register(void)
*描述  :读寄存器函数   地址的最高位为0时-读寄存器
*输入  :要读的寄存器的地址
*输出  :寄存器中的数
*调用  :内部调用
*/
uint8_t read_register(uint8_t adress)
{
        uint8_t temp;
        ON_CS();
        temp=SPI_SendReceive(adress+0x00);
        delayus(75);
        temp=SPI_SendReceive(0xff);
        OFF_CS();
        return temp;
}
/*
*函数名: writr_register(void)
*描述  :对寄存器进行写操作,第一个输入的最高位 为1 即写操作   
*输入  :要写的寄存器的地址  寄存器数值
*输出  :无
*调用  :内部调用
*/
void writr_register(uint8_t adress,uint8_t vlue)
{
        ON_CS();
        SPI_SendReceive(adress+0x80);
        SPI_SendReceive(vlue);
        OFF_CS();
        delayus(51);
}
/*
*函数名: read_busy(void)
*描述  :对寄存器Extended_Config进行写操作,最高位是1表示忙信号,不允许写,最高位是0时允许写寄存器Frame_Period_Max_Bound_Upper and Lower
*           Frame_Period_Min_Bound_Upper and Lower Shutter_Max_Bound_Upper and Lower
*输入  :无
*输出  :0 表示允许写寄存器  1 忙信号不允许写
*调用  :内部调用
*/
uint8_t read_busy(void)                                        //写帧率的判忙  ==1忙
{
        uint8_t temp;
        ON_CS();
        temp=SPI_SendReceive(Extended_Config+0x00);
        delayus(75);
        temp=SPI_SendReceive(0xff);
        temp&=0x80;                                               //Extended_Config最高位与1相与 读dusy位 0时允许写
        OFF_CS();
        return temp;
       
       
}
/*
*函数名: clear_motion(void)
*描述  :对寄存器Motion_Clear进行写操作,使寄存器DX,DY 中的数据清除  
*输入  :无
*输出  :无
*调用  :内部调用
*/
void clear_motion(void)
{
         ON_CS();
         SPI_SendReceive(Motion_Clear+0x80);
         SPI_SendReceive(0xff);                                     //清除X Y数据    编写任何值这个寄存器将导致Delta_X,Delta_Y和内部运动寄存器被清除。
         OFF_CS();
}

/*
*函数名: read_zhenlv(void)
*描述  :对寄存器Frame_Period_Uppe,Frame_Period_Lower进行读操作
*输入  :无
*输出  :帧率
*调用  :内部调用
*/
uint16_t read_zhenlv(void)                                        //读帧率
{  
        return read_register(Frame_Period_Uppe) << 8|read_register(Frame_Period_Lower);   
}
/*
*函数名: Read_Data_burst(void)
*描述  :对寄存器Motion,DX,DY进行读操作 ,从而得到x,y的位移
*输入  :无
*输出  :无
*调用  :主函数调用
*/
void Read_Data_burst(void)
{
          static int SumX;
          static int SumY;
          int sum_x,sum_y;
          unsigned char move=0;
          int  x=0;
          int  y=0;
                ON_CS();
                SPI_SendReceive(0x50);  //0x50 SQUAL寄存器 ???????????????
                delayus(75);
               
                move=SPI_SendReceive(0x02); //0xFF改为0x02         0xFF
                x0=SPI_SendReceive(0x03);        //0xFF改为0x03         0xFF
                y0=SPI_SendReceive(0x04);        //0xFF改为0x04         0xFF
       
  //move=SPI_SendReceive(Motion);
     UARTCharPut(UART1_BASE, move);
       
         UARTCharPut(UART1_BASE, x0);
       
         UARTCharPut(UART1_BASE, y0);
       

                if(x&0x80)     //保留x最高位   x最高位==1 x为负数    ==0 x为正数
                  {
                          //x的二补码转换       
                   /* x -= 1;     
                          x = ~x;       
                          x=(-1)*x;
                          x-=256;*/
                         /*潘梦珠方法  该数是负,把左边最高位的符号位抛弃 把剩下的二进制每一位都取反 取反以后的数值+1,
                          得到的数就是此负的二进制补码的绝对值了 把此绝对值按照二进制转换为十进制,
                          在转换得到的十进制前面加一个负号 就得到了这负的二进制补码对应的十进制数。*/
                          x=x&0x7f;  //去掉最高位
                          x=~x;
                          x=x+1;
                          x=(-1)*x-128;                  
                       
                  }
                if(y&0x80)
                  {
                          //y的二补码转换       
                          y=y&0x7f;
                          y=~y;
                          y=y+1;
                          y=(-1)*y-128;
                   }
                  
                //printf("%d,%d\n",x,y);
                SumX=SumX+x;             //累加X读入的移动数据
                SumY=SumY+y;                         //累加Y读入的移动数据
                  
                OFF_CS();
                delayus(4);
                OFF_CS();
                sum_x=(25.4*(float)SumX *H)/(12*1600);//距离=d_x*(25.4/1600)*n   其中n=像高:物高=8毫米:物长
                sum_y=(25.4*(float)SumY *H)/(12*1600);
                //  printf("%d,%d\n",sum_x,sum_y);
          if((move&0x10)!=1)                //Delta_Y和/或Delta_X缓冲区没有溢出
             {
                        if(move&0x80)                   //运动发生,数据准备读Delta_X和Delta_Y寄存器
                        {
                         //   printf("%d,%d\n",sum_x,0);
                     }
                 
                        else
                        {
                                x=0;
                                y=0;
                        }
                       
             }
            else
                   {
                          x=0;
                          y=0;
                   }
                /**/
}
/*
*函数名: read_average_pixel(void)
*描述  :对寄存器Pixel_Sum进行读操作 ,从而得到平均像素
*输入  :无
*输出  :平均像素
*调用  :主函数调用
*/
float  read_average_pixel(void)                                           //读平均像素
{
  float temp;
  ON_CS();
  temp=SPI_SendReceive(Pixel_Sum);
  delayus(76);
  temp=SPI_SendReceive(0xff);
  temp=temp*0.2844;
  OFF_CS();
  return temp;
}
/*
*函数名: read_pixel(void)
*描述  :
*输入  :无
*输出  :无
*调用  :内部调用
*/
void read_pixel(void)
{
  uint8_t i,j ,regValue, pixelValue,test=1;         
  writr_register(Frame_Capture,0x83);
  delayus(1010);                                                      //等待3帧 (1/3000)*1000000*3+10 =1010us
  //显示数据  30*30=900
  for(i=0;i<30;i++)//列
  {
          for(j=0;j<30;j++) //行
          {
                        regValue=read_register(Frame_Capture);                     //读像素
                        if( test && ((regValue&0x40)==0))                          //找不到第一个像素
                        {
                                               
                        }
                        test=0;
                        pixelValue =(regValue<<2);                             
                        delayus(50);
          }
  }
  ADNS3080_reset();                                                     //重启运行
}
/*
*函数名: read_pixel_burst(void)
*描述  :
*输入  :无
*输出  :无
*调用  :内部调用
*/
void read_pixel_burst(void)                                            //爆发读图像
{
        int i,j;
        writr_register(Frame_Capture,0x83);
        delayus(1010);                                                     //等待3帧 (1/3000)*1000000*3+10 =1010us
        //开始burst读
        ON_CS();
        SPI_SendReceive(0x40);   
        delayus(75);
        for(i=0;i<30;i++)
        {
                for(j=0;j<30;j++)
                {
                        delayus(10);
                }
        }
        OFF_CS();
        delayus(4);
        OFF_CS();            
}






回复评论 (1)

看着感觉很有用啊,下载喵喵。
点赞  2017-3-22 09:37
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复