⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 对摄像头用MCU进行数据采集与分析
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzou ZLG-MCU Development Co.,LTD.
**                                      graduate school
**                                 http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name:			main.c
** Last modified Date:  2004-09-16
** Last Version:		1.0
** Descriptions:		The main() function example template
**
**------------------------------------------------------------------------------------------------------
** Created by:			Chenmingji
** Created date:		2004-09-16
** Version:				1.0
** Descriptions:		The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
********************************************************************************************************/
#include "main.h"
//uint8 pic_camer[120][40];//[60][160];
uint8 camer0[120][160];//[60][320];
uint8 samp_start_flag;
uint8 samp_end_flag;
uint8 end_flag;
uint8 permit_read;
uint8 X_line;
uint8 Y_line;
uint8 LR_move_flag;
uint8 UD_move_flag;
uint8 motorUD_end_flag=3;

#define DELAY_TIME 50
#define SDA 1<<9
#define SCL 1<<8
/***------延时-----***/
void DELAY(uint16 t) /*延时函数*/
{   uint8 i;
    while(t!=0)
    {  for(i=0;i<10;i++);  
       t--;
    }
}
/***-----I2C启动-----***/
void I2C_Start(void)
{
    /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
    IO0SET = SDA;//SDA=1;
    IO0SET = SCL;//SCL=1;
    DELAY(DELAY_TIME/2);
    IO0CLR = SDA;//SDA=0;
    DELAY(DELAY_TIME/25);
    IO0CLR = SCL;//SCL=0;
    DELAY(DELAY_TIME/20);
}
/***-----I2C停止-----***/
void I2C_Stop(void)
{
    /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
    IO0CLR = SCL;//SCL=0;
    IO0CLR = SDA;//SDA=0;
    DELAY(DELAY_TIME/2);
    IO0SET = SCL;//SCL=1;
    DELAY(DELAY_TIME);
    IO0SET = SDA;//SDA=1;
    DELAY(DELAY_TIME);
}
/***-----发送1bit:0-----***/
void SEND_0(void)   /* SEND ACK */
{
    /*发送0,在SCL为高电平时使SDA信号为低*/
    IO0CLR = SDA;//SDA=0;
    DELAY(DELAY_TIME/25);
    IO0SET = SCL;//SCL=1;
    DELAY(DELAY_TIME/25);
    IO0CLR = SCL;//SCL=0;
    DELAY(DELAY_TIME/25);
}
/***-----发送1bit:1-----***/
void SEND_1(void)
{
    /*发送1,在SCL为高电平时使SDA信号为高*/
    IO0SET = SDA;//SDA=1;
    DELAY(DELAY_TIME/25);
    IO0SET = SCL;//SCL=1;
    DELAY(DELAY_TIME/25);
    IO0CLR = SCL;//SCL=0;
    DELAY(DELAY_TIME/25);
}
/***-----发送1bit:等待-----***/
// write don't care bit
void Check_Acknowledge(uint8 sendbit)//void
{   //发送完一个字节后检验设备的应答信号
    if(sendbit & 0x01)
        IO0SET = SDA;      //SDA=1
    else 
        IO0CLR = SDA;      //SDA=0
    DELAY(DELAY_TIME/25);
    IO0SET = SCL;          //SCL=1
    DELAY(DELAY_TIME/25);
    IO0CLR = SCL;          //SCL=0
    DELAY(DELAY_TIME/25);  
}   
/***-----发送1 byte-----***/
void WriteI2CByte(uint8 b)//reentrant
{
    /*向I2C总线写一个字节*/
    uint8 i;
    for(i=0;i<8;i++)
    {   if((b<<i)&0x80)
            SEND_1();
        else
            SEND_0();
    }
}
/***-----读取1 byte-----***/
uint8 ReadI2CByte(void)//reentrant
{   /*从I2C总线读一个字节*/
    uint8 recevise_dt=0,i;
    uint8 BCY=0;
    IO0DIR &= 0xfffffdff;
    for(i=0;i<8;i++)
    { 
        IO0CLR = SCL;
        DELAY(DELAY_TIME/25);
        IO0SET = SCL;
        recevise_dt <<= 1;
        DELAY(DELAY_TIME/25);
        BCY = (IO0PIN>>8) & 0x02;
        if(BCY!=0)       
            recevise_dt += 1;
        IO0CLR = SCL;
        DELAY(DELAY_TIME/25);
    }
    IO0DIR |= 0x00000200;
    return recevise_dt;
}  
/**********以下为读写24c02的函数**********/
void Write_One_Byte(uint8 addr,uint8 thedata)
{   I2C_Start();
    WriteI2CByte(0x42);
    Check_Acknowledge(0x00);
    WriteI2CByte(addr);
    Check_Acknowledge(0x00);
    WriteI2CByte(thedata);
    Check_Acknowledge(0x00);
    I2C_Stop();    
}

uint8 Read_One_Byte(uint8 addr,uint8 addrr)
{   uint8 recevise_data;
    I2C_Start();
    WriteI2CByte(0x42);
    Check_Acknowledge(0x00);
    WriteI2CByte(addrr);
    Check_Acknowledge(0x00);
    I2C_Stop();
    DELAY(DELAY_TIME/25);
    I2C_Start();    
    WriteI2CByte(0x43);
    Check_Acknowledge(0x01);
    recevise_data = ReadI2CByte();
    Check_Acknowledge(0x01);
    I2C_Stop();
    return recevise_data;
}
//#define XY_use
/*
*******************************************************************************
** 函数名称:INT0_IRQ()
** 函数功能:camer0场中断
** 入口参数:中断口电平发生改变
** 出口参数:处理中断服务程序
*******************************************************************************
*/uint8 gap;
uint16 gbn;
uint16 dno;
void __irq IRQ_Eint0(void)
{   //IO0SET = RR;
    if(samp_end_flag ==1)                      // 采样结束
    {   end_flag =1; VICIntEnClr = 1<<0x0f;    // 置采样结束标志,同时关闭行信号中断
    }
    else  if(samp_start_flag ==0)                                     // 没有结束
    {   gap = 0;gbn =0;                        // 清空纵坐标
        samp_start_flag = 1;                   // 置开始采样标志
        VICIntEnable = 1<<0x0f;                // 开行中断
    }
    EXTINT |= 0x01;
    VICVectAddr = 0x00;			               // 中断处理结束
    //IO0CLR = RR;
}
/*
*******************************************************************************
** 函数名称:INT1_IRQ()
** 函数功能:camer0行中断//  VSYNC 信号
** 入口参数:中断口电平发生改变
** 出口参数:处理中断服务程序
*******************************************************************************
*/
void __irq IRQ_Eint1(void)
{   static uint8 start_samp=0;                  // 是否允许采样互锁
    if(samp_start_flag ==1)                     // 检测到可以开始采样标志
    {   //if(((IO0PIN>>8)&0x04) !=0)              //HREF
        {   if(gbn<239)                         // 采样240行
            {  if(gbn%2 ==0)                    // 2行采集一次
               {  gap++; dno =0;
               }
               gbn++;                           // 调整采样参数
            }
            else                                // 已经采完
            {  samp_end_flag =1;                // 置采样结束标志
               samp_start_flag=0;               // 清开始采样标志
               start_samp = 0;                  // 
               VICIntEnClr = 1<<0x10;           // 关闭采样clk中断
            }
            if(samp_end_flag==0 && start_samp==0)//判断是不是第一次开始采样
            {   start_samp =1;                   //互锁
                VICIntEnable = 1<<0x10;          //开采样clk脉冲中断
            }
        }
    }
    EXTINT |= 0x02;
    VICVectAddr = 0x00;			                 // 中断处理结束   
}
/*
*******************************************************************************
** 函数名称:INT2_IRQ()
** 函数功能:camer0行中断//  VSYNC 信号
** 入口参数:中断口电平发生改变
** 出口参数:处理中断服务程序
*******************************************************************************
*/
void __irq IRQ_Eint2(void)
{   uint8 i;
    if(samp_start_flag ==1)                      // 开始采样标志                    
    {   if(((IO0PIN>>8)&0x04) !=0)               // 判断HREF是否有效
        {   if(dno%2 ==0)                        // 每格4点采样一点
            {   i = (IO1PIN>>16)&0xff;           // 得到数据 
                camer0[gap-1][dno/2]=i;              // 放到缓冲期终
            }
            dno++;                               //  调整到下一个像素点
        }
    }   
    EXTINT |= 0x04; 
    VICVectAddr = 0x00;			                  // 中断处理结束
}
/*******************************************************************************************
**函数名称:camerINT_Init()
**函数功能:camer照相的行与场的中断。
**入口参数:行与场电平变法
**返 回 值:相应各自的中断
**说    明:进入各自的中断服务处理程序
*******************************************************************************************/ 
void camerINT_Init()
{   
    EXTMODE  = 0x07;                                                          // 使用边沿触发外部中断
    EXTPOLAR = 0x04;                                                          // 开0、1、2、3中断,下降沿   
}
/*
*******************************************************************************
** 函数名称:void LR_UD_move(uint8 x,uint8 y)
** 函数功能:步进电机要动作的方向
** 入口参数:当前camera采集到的像素点位置
** 出口参数:给出动作标志
*******************************************************************************
*/
void LR_UD_judge(uint8 x,uint8 y)
{   /*if(x>90)      LR_move_flag =1;           // 像素点在右边,摄像头右转
    else if(x>1&&x<70) LR_move_flag =2;    // 像素点在左边,摄像头左转
    else if((x>70 && x<90) || x==0)  
                  LR_move_flag =0;           // 像素点在水平方向的中间位置、摄像头不动
    if(y>70)      UD_move_flag =1;           // 像素点在下边,摄像头向下转
    else if(y>1&&y<50) UD_move_flag =2;    // 像素点在上方,摄像头向上转
    else if((y>50&&y<70) || y==0)         
                  UD_move_flag =0;           // 像素点在垂直方向的中间位置、摄像头不动*/
    if(x>90)      LR_move_flag =1;
    else if(x>70) LR_move_flag =0;
    else if(x>1)  LR_move_flag =2;
    else          LR_move_flag =0;
    
    /*if(y>70)      UD_move_flag =1;
    else if(y>50) UD_move_flag =0;
    else if(y>1)  UD_move_flag =2;
    else          UD_move_flag =0;*/
}
/*
*******************************************************************************
** 函数名称:void LR_UD_move(uint8 x,uint8 y)
** 函数功能:步进电机要动作的方向
** 入口参数:当前camera采集到的像素点位置
** 出口参数:给出动作标志
*******************************************************************************
*/uint8 motor_end_flag=3;
void motor_move(void)
{   /*if(LR_move_flag ==0)                     // 水平方向在中间,不需要转动
    {   //IO0CLR |= 0x00000080;                // 关使能
        //VICIntEnClr = 1 << 0x05;
        motor_end_flag = 1;	
    }
    else                                     // 水平方向不在中间,需要转动
    {   //IO0CLR |= 0x00000080;                // 开使能
        if(LR_move_flag ==1)                 // 在右边
            IO0CLR = DIR;
        else if(LR_move_flag ==2)            // 在左边
            IO0SET = DIR;
    } */
    switch(LR_move_flag)
    {   case 0:motor_end_flag = 1;break;
        case 1:IO0CLR = DIR;break;
        case 2:IO0SET = DIR;break;
    }
}

/*
*********************************************************************************************************
** 函数名称 :IRQ_T1()
** 函数功能 :T1定时器中断服务程序
** 入口参数 :无
** 出口参数 :匹配输出脉冲
*********************************************************************************************************
*/
void __irq IRQ_T1 (void)
{  //static uint8 re_p;
   LR_UD_judge(X_line,Y_line);
   motor_move();
   T1IR = 0x01;
   VICVectAddr = 0x00;			            // 中断处理结束
}
/*
*********************************************************************************************************
** 函数名称 :T1_Init()
** 函数功能 :T1定时器初始化,设置工作模式。
** 入口参数 :
*********************************************************************************************************
*/
void T1_Init ()
 {  T1TC   = 0;							// 定时器初值设置为0
    T1PR   = 0;							// 时钟不分频,(1秒计数Fpclk个脉冲)
    T1MCR  = 0x03;						// 设置T1MR0匹配后复位T1TC,并产生中断标志
    T1EMR  = 0x30;                      // T1MR0匹配否MAT1.0输出翻转
    T1MR0  = Fpclk / 128;				    // 匹配寄存器MR0等于1/3的计数频率,通过改变来改变
    T1TCR  = 0x01;                      // 定时器启动

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -