基于恩智浦MK60DN512Z系列单片机的智能模型车主程序集
作者 徐挺
/**********************************************************
函数名称:主程序
*********************************************************/

void main(void) {
DisableInterrupts; //关闭中断
PLL_Init(PLL180); //初始化时钟频率,总线时钟频率为180MHz
LCD_Init(); //TFT显示屏初始化
OV7725_Init(10) ; //OV7725摄像头初始化
Motor_Init(); //电机初始化
Ultrasonic_Init(); //超声波测距模块初始化
PIT_Init(PIT0,500); //PIT0号定时中断器初始化,每定时500ms中断一次
PIT_Init(PIT1,200); //PIT1号定时中断器初始化,每定时200ms中断一次
set_irq_priority(89, 0); //外部PORTC中断设为0优先级(最高)
set_irq_priority(68, 1); //PIT0定时器中断设为1优先级
set_irq_priority(69, 2); //PIT1定时器中断设为2优先级
EnableInterrupts; //开启中断
while(1) {
Get_Use_Image(); //摄像头原始帧120320像素压缩为60100像素图像
EnableInterrupts; //开启中断(某些中断子程序结束后会关闭,故重开)
Draw_change(Image_Use); //将摄像头采集的图像格式转换为TFT屏显示的格式
Show_pic(15,0,114,60,Image_change); //TFT屏实时显示摄60100像素图像
Line_trace(); //智能车寻线行驶子程序
} }
外部PORTC中断子程序代码如下:
void PORTC_Interrupt(void) { //PORTC中断子程序入口,采集原始帧120
320像素
int n=6; //设置摄像头单帧图像每行像素采集行中断
if((PORTC_ISFR & (1<<n))) {
PORTC_ISFR |= (1<<n); //行中断标志位清除
if(VSY_Flag0) return; //检查是否此帧图像所有行(120行)采集完成
DMA_PORTx2BUFF_Init (DMA_CH4, (void *)&PTD_BYTE1_IN, Image_Data[Line_Cont], PTE6, DMA_BYTE1,640, DMA_rising_down); //DMA初始化,每行像素采集至Image_Data
DMA_EN(DMA_CH4); //启动DMA,摄像头图像采集
Line_Cont++;
if(Line_Cont120) { //每行采集至指定行数(120行),1帧采集结束
time_delay_ms(1);
Line_Cont = 0; //图像行序数回归第0行
VSY_Flag=0; //场中断标志位清0
DMA_DIS(DMA_CH4); //关闭DMA
DisableInterrupts; } } //关闭中断功能
n=7; //设置摄像头每一帧图像采集场中断
if((PORTC_ISFR & (1<<n))) {
PORTC_ISFR |= (1<<n); //场中断标志位清除
Line_Cont = 0; //图像行序数回归第0行
VSY_Flag=1; } } //场中断标志位置1,新1帧图像可重新开始采集
PIT0定时器中断,中断子程序代码如下:
void PIT0_Interrupt(){ //PIT0中断子程序函数入口
PIT_Flag_Clear(PIT0); //清PIT0中断标志位
distance=Test_HCSR(); //运行超声波测距子程序,测距值赋值给distance
if(distance<5) { //判定如果distance值小于5cm
Motor_Run_1(0,1000) ;
Motor_Run_2(0,1000) ;
time_delay_ms(200); //小车后退避障
Motor_Run_1(1,1000) ;
Motor_Run_2(0,1000) ;
time_delay_ms(200); } } //小车右大转弯绕开障碍物
PIT1定时器中断,中断子程序代码如下:
void PIT1_Interrupt(){ //PIT1中断子程序函数入口
PIT_Flag_Clear(PIT1); //清PIT1中断标志位
stop_car=Test_TRAFFIC() //运行红绿灯检测程序,反馈值赋值给stop_car
if(stop_car==1) { //判定是否stop_car值为1(1红灯,0绿灯)
Motor_Run_1(0,0) ;
Motor_Run_2(0,0) ; } } //小车停止

/********************************************************************************************
********************************************************************************************/

基于恩智浦MK60DN512Z系列单片机的智能模型车子程序集
作者 徐挺
/**********************************************************
函数名称:大津算法
GetOSTU()
**********************************************************/
unsigned char GetOSTU(unsigned char tmImage[60][100]) {
int i,j,Amount=0, PixelBack=0,PixelIntegralBack=0,PixelIntegral=0, PixelIntegralFore=0,PixelFore=0,MinValue,MaxValue,Threshold = 0;
float P1, P2,m1, m2, SigmaB, Sigma; // 类间方差
unsigned char HistoGram[94];
for (j = 0; j < 94; j++) HistoGram[j] = 0; //初始化灰度直方图
for (j = 0; j < 60; j++)
for (i = 0; i < 100; i++)
HistoGram[tmImage[j][i]]++; //统计灰度级中每个像素在整幅图像中的个数
for (MinValue = 0; MinValue < 94 && HistoGram[MinValue] == 0; MinValue++) ; //获取最小灰度的值
for(MaxValue=93; MaxValue>MinValue&&HistoGram[MinValue]0; MaxValue–) ; //获取最大灰度的值
if (MaxValue == MinValue) return MaxValue; // 图像中只有一个颜色
if (MinValue+1MaxValue) return MinValue; // 图像中只有二个颜色
for(j=MinValue; j<=MaxValue; j++) Amount+=HistoGram[j];// 像素总数
PixelIntegral = 0;
for(j=MinValue; j<=MaxValue; j++)
PixelIntegral+= HistoGram[j] * j; //灰度值总数
SigmaB = -1;
for(j=MinValue; j<MaxValue; j++)
{
PixelBack = PixelBack + HistoGram[j]; // C1类像素点数
PixelFore = Amount - PixelBack; // C2类像素点数
P1 = (float)PixelBack / Amount; // C1类灰度值百分比
P2 = (float)PixelFore / Amount; // C2类灰度值百分比
PixelIntegralBack+= HistoGram[j] * j; // C1类灰度值
PixelIntegralFore=PixelIntegral-PixelIntegralBack;// C2类灰度值
m1 = (float)PixelIntegralBack / PixelBack; // C1类平均灰度值
m2 = (float)PixelIntegralFore / PixelFore; //C2类平均灰度值
Sigma = P1 * P2 * (m1 - m2) * (m1 - m2); //计算类间方差
if (Sigma > SigmaB) {
SigmaB = Sigma;
Threshold = j; } //遍历最大的类间方差g ,找出最大类间方差以及对应阈值
} return Threshold; } //返回最佳阈值;

/**********************************************************
函数名称:噪声滤波
void Pixle_Filter()
**********************************************************/
void Pixle_Filter(unsigned char Pixle[60][100]) {
int r, c; //r为行,c为列
for(r=1; r<60-1; r++)
for(c=1; c<100-1; c=c+1) {
if((Pixle[r][c]==0)&&(Pixle[r-1][c]+Pixle[r+1][c]+Pixle[r][c+1]
+Pixle[r][c-1]>2)) Pixle[r][c]=1;
else if((Pixle[r][c]==1)&&(Pixle[r-1][c]+Pixle[r+1][c]+Pixle[r][c+1]
+Pixle[r][c-1]<2)) Pixle[r][c]=0; } }

/**********************************************************
函数名称:拟合直线求K值子程序
void K_B()
**************************************************/
void K_B(unsigned char center[]){
int i;
float num=0, sum_x=0,sum_y=0,sum_xy=0,sum_x2=0;
for(i=0;i<60;i++) {
if(center[i]!=0) {
sum_x=sum_x+center[i];
num++; } }
for(i=0;i<60;i++) {
if(center[i]!=0) sum_y=sum_y+i; }
for(i=0;i<60;i++) {
if(center[i]!=0) sum_xy=sum_xy+i
center[i]; }
for(i=0;i<60;i++) {
if(center[i]!=0) sum_x2=sum_x2+center[i]center[i]; }
K = (num
sum_xy-sum_x
sum_y)/(num
sum_x2-sum_x
sum_x) ;
B = (sum_x2
sum_y-sum_x
sum_xy)/(num
sum_x2-sum_x
sum_x) ; }

/**********************************************************
函数名称:实时控制电机 ,小车左右行驶执行函数
void Turn_control()
**********************************************************/
void Turn_control(){
if(K>=3||K<=-3) {
Motor_Run_1(1,400) ;
Motor_Run_2(1,400) ; } //小车前进
else if(K<3&&K>1) {
Motor_Run_1(1,100) ;
Motor_Run_2(1,500) ;
time_delay_ms(100); } //小车左转
else if(K>-3&&K<-1) {
Motor_Run_1(1,500) ;
Motor_Run_2(1,100) ;
time_delay_ms(100); } //小车右转
else if(K<=1&&K>0) {
Motor_Run_1(0,500) ;
Motor_Run_2(1,500) ;
time_delay_ms(100); } //小车大左转
else if(K>=-1&&K<0) {
Motor_Run_1(1,500) ;
Motor_Run_2(0,500) ;
time_delay_ms(100); } //小车大右转
else {
Motor_Run_1(1,0) ;
Motor_Run_2(1,0) ; } } //小车原地停止

/**********************************************************
函数名称:R、G、B分量分解函数
RGB_Change()
******************************************************/
void RGB_Change(void)
{ int i,j;
for(i=0;i<60;i++)
for(j=0;j<100;j++){
Pixle_R[i][j]=(Image_Use[i][2
j]&0xf8)>>3;
Pixle_G[i][j]=((Image_Use[i][2
j]&0x07)<<3)+((Image_Use[i][2
j+1]&0xe0)>>5);
Pixle_B[i][j]=Image_Use[i][2
j+1]&0x1f;}
}

/**********************************************************
函数名称:LCD_init()
**********************************************************/
void LCD_Init(void)
{
GPIO_Init(PORTC,19,GPO,1);
GPIO_Init(PORTC,18,GPO,1);
GPIO_Init(PORTC,17,GPO,1);
GPIO_Init(PORTC,16,GPO,1);

LQTFT_RST=0;
time_delay_ms(200);
LQTFT_RST=1;
time_delay_ms(50);
LCD_write_command(0x11);//start OSC
time_delay_ms(100);  LCD_write_command(0xB1);//frame rate control
LCD_write_para8(0x05);
LCD_write_para8(0x3A);
LCD_write_command(0x36);//镜像控制?
LCD_write_para8(0x08);  //
LCD_write_command(0xB2);
LCD_write_para8(0x05);
LCD_write_para8(0x3A);
LCD_write_command(0xB3);
LCD_write_para8(0x05);
LCD_write_para8(0x3A);
LCD_write_para8(0x05);
LCD_write_para8(0x3A);
LCD_write_command(0xB4);//inversion setting
LCD_write_para8(0x00);  //0x00=dot inversion
LCD_write_command(0xC0);//Power Control 1
LCD_write_para8(0xAA);  //AVDD=5V;GVDD=4.2V
LCD_write_para8(0x0A);  //GVCL=-4.2V
LCD_write_para8(0x84);  //Mode=AUTO;VRHP=VRHN=0
LCD_write_command(0xC1);//Power Control 2
LCD_write_para8(0xC0);  //V25=2.4V;VGH=2AVDD+VGH25-0.5=11.9V;VGL=-7.5V
LCD_write_command(0xC2);//Power Control 3
LCD_write_para8(0x0D);  //
LCD_write_para8(0x00);  //
LCD_write_command(0xC3);//Power Control 4
LCD_write_para8(0x8D);  //
LCD_write_para8(0x2A);  //
LCD_write_command(0xC4);//Power Control 5
LCD_write_para8(0x8D);
LCD_write_para8(0xEE);
LCD_write_command(0xC5);//VCOM setting
LCD_write_para8(0x06);  //
LCD_write_command(0xE0);
LCD_write_para8(0x06);
LCD_write_para8(0x1C);
LCD_write_para8(0x10);
LCD_write_para8(0x14);
LCD_write_para8(0x30);
LCD_write_para8(0x2B);
LCD_write_para8(0x24);
LCD_write_para8(0x29);
LCD_write_para8(0x28);
LCD_write_para8(0x26);
LCD_write_para8(0x2E);
LCD_write_para8(0x39);
LCD_write_para8(0x00);
LCD_write_para8(0x02);
LCD_write_para8(0x01);
LCD_write_para8(0x10);
LCD_write_command(0xE1);
LCD_write_para8(0x06);
LCD_write_para8(0x1C);
LCD_write_para8(0x10);
LCD_write_para8(0x14);
LCD_write_para8(0x30);
LCD_write_para8(0x2B);
LCD_write_para8(0x24);
LCD_write_para8(0x29);
LCD_write_para8(0x28);
LCD_write_para8(0x26);
LCD_write_para8(0x2E);
LCD_write_para8(0x39);
LCD_write_para8(0x00);
LCD_write_para8(0x02);
LCD_write_para8(0x01);
LCD_write_para8(0x10);
LCD_write_command(0x3A);//
LCD_write_para8(0x05);  //RGB 16-bit
LCD_write_command(0x29);//display on
time_delay_ms(10);
LCD_display_full(RED);

}

/DRIVE IC寄存器寻址 8080 SERIES*************/
void LCD_write_command(unsigned char cmd)
{
unsigned char i;
LQTFT_A0=0; //A0=0发送命令
LQTFT_CS=0;
for(i=0;i<8;i++)
{
LQTFT_SCK=0;
if((cmd&0x80)==0x80) //高位先发送
LQTFT_SDA=1;
else
LQTFT_SDA=0;
//LQTFT_SDA =((0x80&cmd>0)?1:0);
LQTFT_SCK = 1;
cmd = (cmd<<1);
}
LQTFT_CS=1;
}

/DRIVE IC寄存器写数据 8080 SERIES*************/
void LCD_write_para8(unsigned char dat)
{
unsigned char i;
LQTFT_A0=1; //A0=1发送数据
LQTFT_CS=0;
for(i=0;i<8;i++)
{
LQTFT_SCK=0;
if((dat&0x80)==0x80)
LQTFT_SDA=1;
else
LQTFT_SDA=0;
//LQTFT_SDA =((0x80&dat>0)?1:0);
LQTFT_SCK = 1;
dat = (dat<<1);
}
LQTFT_CS=1;
}

/DRIVE IC GDRAM 写数据 16BITS 8080 SERIES*************/
void LCD_write_para16(unsigned int dat)
{
unsigned char i,buf;
LQTFT_A0=1;
LQTFT_CS=0;
buf = (unsigned char)(0xFF&(dat>>8));
for(i=0;i<8;i++)
{
LQTFT_SCK=0;
if((buf&0x80)==0x80)
LQTFT_SDA=1;
else
LQTFT_SDA=0;
//LQTFT_SDA =((0x80&buf>0)?1:0);
LQTFT_SCK=1;
buf=(buf<<1);
}
LQTFT_CS=1;

buf = (unsigned char)(0xFF&dat);
LQTFT_CS=0;
for(i=0;i<8;i++)
{LQTFT_SCK=0;if((buf&0x80)==0x80)LQTFT_SDA=1;elseLQTFT_SDA=0;//LQTFT_SDA =((0x80&buf>0)?1:0);LQTFT_SCK =1;buf=(buf<<1);
}
LQTFT_CS=1;

}

/**********************************************************
函数名称:LCD_SetPos()
入口参数:起始终止坐标
出口参数:无
时间:2016/11/12
功能说明:重新定位输入信息位置
其他说明:无
**********************************************************/
void LCD_SetPos(unsigned char xs,unsigned char ys,unsigned char xe,unsigned char ye)
{
LCD_write_command(0x2A); //Colulm addRSTs set
LCD_write_para8(0x00); //行起始坐标高8位,始终为零
LCD_write_para8(xs); //行起始坐标低8位
LCD_write_para8(0x00); //行终止坐标高8位,始终为零
LCD_write_para8(xe); //行终止坐标低8位
LCD_write_command(0x2B); //Colulm addRSTs set
LCD_write_para8(0x00); //列起始坐标高8位,始终为零
LCD_write_para8(ys); //列起始坐标低8位
LCD_write_para8(0x00); //列终止坐标高8位,始终为零
LCD_write_para8(ye); //列终止坐标低8位
LCD_write_command(0x2C); //GRAM接收MCU数据或命令
}

/**********************************************************
函数名称:LCD_address_rst()
入口参数:无
出口参数:无
时间:2016/11/12
功能说明:重置地址
其他说明:无
**********************************************************/
void LCD_address_rst(void)
{
LCD_write_command(0x2a); //配置MCU可操作的LCD内部RAM横坐标起始、结束参数
LCD_write_para8(0x00); //横坐标起始地址0x0000
LCD_write_para8(0x00);
LCD_write_para8(0x00); //横坐标结束地址0x007f(127)
LCD_write_para8(0x7f);
LCD_write_command(0x2b); //配置MCU可操作的LCD内部RAM纵坐标起始结束参数
LCD_write_para8(0x00); //纵坐标起始地址0x0000
LCD_write_para8(0x30);
LCD_write_para8(0x00); //纵坐标结束地址0x009f(159)
LCD_write_para8(0x70);
LCD_write_command(0x2C); //GRAM接收MCU数据或命令
}

/*********************************************************/
//延时函数
void time_delay(unsigned int t)
{
unsigned int i,j;

for(j=0;j<t;j++)for(i=0;i<1000;i++);

}

/**********************************************************
函数名称:LCD_display_full()
入口参数:color为常用的需要显示的颜色(已经提前定义),color为
NULL时,则可将不常用颜色放入dat中加以显示
出口参数:无
时间:2012-09-09
功能说明:全屏显示单色画面
其他说明:无
**********************************************************/
void LCD_display_full(unsigned int color)
{
unsigned int i,j;

    LCD_SetPos(0,0,XMAX,YMAX);
for(i=0;i<XMAX;i++)
{ for(j=0;j<YMAX;j++){            LCD_write_para16(color);}
}

}
void LCD_CLS(void)
{
LCD_display_full(BLACK);
}

/显示图片****************/

void show_pic(unsigned char xs,unsigned char ys,unsigned char xe,unsigned char ye,unsigned char *ppic)
{
unsigned int i,j,k=0;

LCD_SetPos(xs,ys,xe,ye);
for(i=0;i<xe-xs;i++)
{ for(j=0;j<ye-ys;j++){           LCD_write_para16(((unsigned int)ppic[k])<<8|ppic[k+1]);          k+=2;}
}

}

/------------------------------------------------------------------------------------------------------
【函 数】OV7725_Init
【功 能】摄像头初始化
【参 数】fps 帧率
【返 回 值】无
【实 例】推荐使用50帧的
【注意事项】注意K60性能有限,太高帧率会出问题
--------------------------------------------------------------------------------------------------------
/
void OV7725_Init(uint8_t fps)
{
uint8_t id[2]; //存放摄像头id
uint8_t ack = 0; //检验所有寄存器操作是否出错
uint16_t width = OV7725_IMAGEW, height = OV7725_IMAGEH;
uint16_t hstart, vstart, hsize;
//摄像头寄存器设置
GPIO_Init(PORTE,4,GPI_UP,1); //配置为GPIO功能
GPIO_Init(PORTE,5,GPI_UP,1); //配置为GPIO功能
EXTI_Init(PTC,6,rising_down); //行中断
EXTI_Init(PTC,7,falling_up); //场中断

GPIO_Init(PORTD,8,0,0);
GPIO_Init(PORTD,9,0,0);
GPIO_Init(PORTD,10,0,0);
GPIO_Init(PORTD,11,0,0);
GPIO_Init(PORTD,12,0,0);
GPIO_Init(PORTD,13,0,0);
GPIO_Init(PORTD,14,0,0);
GPIO_Init(PORTD,15,0,0);     //注意不要使用灯PD15OV7725_SoftwareReset();          //寄存器恢复初始值
time_delay_ms(50);
/*7725最大分辨率 640 * 480*/ack += OV7725_Init_Regs();     //先按官方的默认初始化 VGA 后面需要再改ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM2_REG, 0x03);  //输出驱动能力 Bit[4]: 睡眠模式 Bit[1:0]: 驱动能力00: 1x 01: 2x 10: 3x 11: 4x

#if 1 //RGB模式
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM7_REG, 0x46); // 使用QVGA 和 RGB565 格式

ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM3_REG, 0x00);//Bit[6]: 0水平镜像关 1水平镜像开  注意开启水平镜像时最好开启0x32寄存器的Bit[7]:镜像图像边缘对齐-在镜像模式下应该设置为1hstart = (0x3fU << 2U);   //图像水平开始位置 使用VGA时 为0x23
vstart = (0x03U  << 1U) ;   //图像垂直开始位置 使用VGA时 为0x07

#else //灰度模式

ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM7_REG, 0x43);  //  使用QVGA 和 Bayer RAW 格式
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM3_REG, 0x00);hstart = 0x3fU << 2U;   //图像水平开始位置
vstart = 0x03U << 1U;   //图像垂直开始位置

#endif

ack += SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_CNST_REG, 0x20);
OV7725_SetFPS(fps);ack += SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_EXHCL_REG, 0x00); //虚拟像素插入LSB用于在水平方向插入虚拟像素的LSB
ack += SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_ADVFL_REG, 0x00); //垂直同步插入虚拟行(1位等于1行)的LSB
ack += SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_ADVFH_REG, 0x00); //垂直同步插入虚拟行的MSB
/* Resolution and timing. */
hsize = width + 16;/* 设置输出图片大小. *///水平起始位置高位  因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了10位数据,这里是高8位,剩下的两位放在OV7725_HREF_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_HSTART_REG, hstart >> 2U); //水平宽度高位      因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了10位数据,这里是高8位,剩下的两位放在OV7725_HREF_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_HSIZE_REG, hsize >> 2U);  //垂直起始位置高位  因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了9位数据,这里是高8位,剩下的两位放在OV7725_HREF_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VSTART_REG, vstart >> 1U); //垂直高度高位      因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了9位数据,这里是高8位,剩下的两位放在OV7725_HREF_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VSIZE_REG, height >> 1U);   //水平输出宽度高位  因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了10位数据,这里是高8位,剩下的两位放在OV7725_EXHCH_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_HOUTSIZE_REG, width >> 2U); //垂直输出高度高位  因为寄存器是8位的 最大255,像素最大640 * 480 放不下,用了9位数据,这里是高8位,剩下的两位放在OV7725_EXHCH_REG中
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VOUTSIZE_REG, height >> 1U);//水平宽度和垂直高度的低位
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_HREF_REG,((vstart & 1U) << 6U) | ((hstart & 3U) << 4U) | ((height & 1U) << 2U) | ((hsize & 3U) << 0U)); //水平输出和垂直输出的低2位和低1位
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_EXHCH_REG, ((height & 1U) << 2U) | ((width & 3U) << 0U));

}

/------------------------------------------------------------------------------------------------------
【函 数】OV7725_SetFPS
【功 能】设置FPS
【参 数】fps
【返 回 值】无
【实 例】
【注意事项】配置的是摄像头的帧率输出,帧率越高,单片机的新能要求越高
--------------------------------------------------------------------------------------------------------
/
void OV7725_SetFPS(uint8_t fps)
{
if(fps > 75)
{
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM4_REG, 0xC1); //PCLK 48M
}
else
{
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM4_REG, 0x41); //PCLK 24M
}
uint16_t dm_lnl = 0; //虚拟行
uint8_t div = 1; //时钟分频系数
if(fps > 150)
{
fps = 150;
div = 1;
dm_lnl = 0;
}
else if(fps > 75)
{
div = 1;
dm_lnl = (uint16_t)((150 - fps) / 150.0 * (OV7725_IMAGEH + 36*(div + 1)));
}
else if(fps > 50)
{
div = 1;
dm_lnl = (uint16_t)((75 - fps) / 75.0 * (OV7725_IMAGEH + 36*(div + 1)));
}
else if(fps > 37)
{
div = 2;
dm_lnl = (uint16_t)((50 - fps) / 50.0 * (OV7725_IMAGEH + 36*(div + 1)));
}
else if(fps > 18)
{
div = 3;
dm_lnl = (uint16_t)((37.5 - fps) / 37.5 * (OV7725_IMAGEH + 36*(div + 1)));
}
else
{
div = 14;
dm_lnl = 0;
}
/*时钟配置 时钟 = PCLK * 4 / ((1+1)4) 时钟越高,帧率越快 不过DMA可能接受不了会有噪点
Bit[6]: 直接使用外部时钟(没有时钟预刻度可用)
Bit[5:0]: 时钟 = PCLK × 锁相环倍频器 /[(CLKRC[5:0] + 1) × 4]
/
SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_CLKRC_REG, div);

/*虚拟行低八位, 增加虚拟行可以降低帧率,适当添加把帧率配置到自己想要的帧率*/
SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_DM_LNL_REG, (uint8_t)dm_lnl);  /*虚拟行高八位*/
SCCB_RegWrite(OV7725_SCCB_ADDR, OV7725_DM_LNH_REG, (uint8_t)(dm_lnl>>8));

}
/------------------------------------------------------------------------------------------------------
【函 数】OV7725_Init_Regs
【功 能】自动曝光 VGA
【参 数】无
【返 回 值】无
【实 例】
【注意事项】
--------------------------------------------------------------------------------------------------------
/
uint8_t OV7725_Init_Regs(void)
{
uint8_t ack = 0;
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x3d, 0x03);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x42, 0x7f);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x4d, 0x09);

ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x64, 0xff);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x65, 0x20);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x66, 0x00);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x67, 0x48);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x0f, 0xc5);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x13, 0xff);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x63, 0xe0);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x14, 0x11);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x22, 0x3f);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x23, 0x07);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x24, 0x40);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x25, 0x30);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x26, 0xa1);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x2b, 0x00);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x6b, 0xaa);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x0d, 0x41);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x90, 0x05);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x91, 0x01);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x92, 0x03);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x93, 0x00);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x94, 0x90);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x95, 0x8a);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x96, 0x06);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x97, 0x0b);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x98, 0x95);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x99, 0xa0);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x9a, 0x1e);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x9b, 0x08);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x9c, 0x20);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x9e, 0x81);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0xa6, 0x04);ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x7e, 0x0c);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x7f, 0x16);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x80, 0x2a);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x81, 0x4e);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x82, 0x61);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x83, 0x6f);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x84, 0x7b);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x85, 0x86);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x86, 0x8e);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x87, 0x97);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x88, 0xa4);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x89, 0xaf);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x8a, 0xc5);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x8b, 0xd7);
ack += SCCB_RegWrite(OV7725_SCCB_ADDR,0x8c, 0xe8);
return ack;

}

/------------------------------------------------------------------------------------------------------
【函 数】OV7725_SoftwareReset
【功 能】复位摄像头 恢复默认配置
【参 数】无
【返 回 值】无
【实 例】
【注意事项】
--------------------------------------------------------------------------------------------------------
/
void OV7725_SoftwareReset(void)
{
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM7_REG, 0x80);
}
/------------------------------------------------------------------------------------------------------
【函 数】OV7725_LightModeConfigs
【功 能】灯光配置
【参 数】0:自动模式1:晴天2,多云3,办公室4,家里5,夜晚
【返 回 值】无
【实 例】
【注意事项】
--------------------------------------------------------------------------------------------------------
/
void OV7725_LightModeConfigs(uint8_t mode)
{
switch(mode)
{
case 1: //晴天
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xfd);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x5a);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x5c);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0x65);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);
break;
case 2: //多云
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xfd);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x58);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x60);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0x65);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);
SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);

        break;case 3:  //办公室SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xfd);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x84);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x4c);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0x65);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);break;case 4:   //家里SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xfd);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x96);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x40);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0x65);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);break;case 5:   //晚上SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xff);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0xe5);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);break;default:   //自动模式SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM8_REG, 0xff);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_BLUE_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_RED_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_COM5_REG, 0x65);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFL_REG, 0x00);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_ADVFH_REG, 0x00);break;
}   }

/------------------------------------------------------------------------------------------------------
【函 数】OV7725_SpecialEffectConfigs
【功 能】特效配置
【参 数】0:普通模式 1.黑白 2.复古 3,偏蓝4,偏红5,偏绿 6,负片
【返 回 值】无
【实 例】
【注意事项】
--------------------------------------------------------------------------------------------------------
/
void OV7725_SpecialEffectConfigs(uint8_t mode)
{

switch(mode)
{case 1:  //黑白SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x26);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x80);break;case 2:  //复古SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x1e);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x40);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0xa0);break;case 3:  //偏蓝SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x1e);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0xa0);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x40);break;case 4:   //偏红SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x1e);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x40);break;case 5:   //偏绿SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x1e);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x60);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x60);break;case 6:   //负片SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x46);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x00);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x00);break;default:   //普通模式SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_SDE_REG, 0x06);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_UFIX_REG, 0x80);SCCB_RegWrite(OV7725_SCCB_ADDR,OV7725_VFIX_REG, 0x80);break;
}

}

/*********************************************************************
*摄像头SCCB底层驱动

  • /
    /
    **
  • 北京龙邱智能科技 KV58智能车母板
  • 函数名称:void SCCB_Init(void)
  • 功能说明:配置SCCB所用引脚为GPIO功能,暂时不配置数据方向
  • 参数说明:无
  • 函数返回:无
  • 修改时间:2017年12月5日
  • 备 注:
    *************************************************************************/
    void SCCB_Init(void)
    {
    GPIO_PinInit(SCCB_SCL_PIN, GPI_UP, 1);//配置为GPIO功能
    // PORTE_BASE_PTR->PCR[4] |= 0x03; //上拉
    GPIO_PinInit(SCCB_SDA_PIN, GPI_UP, 1);//配置为GPIO功能
    // PORTE_BASE_PTR->PCR[5] |= 0x03; //上拉

}

/*************************************************************************

  • 函数名称:void SCCB_Wait(void)
  • 功能说明:SCCB等待演示
    /
    void SCCB_Wait(void)
    {
    uint16_t i=0;
    for(i=0;i<100;i++)
    {
    asm (“nop”);
    }
    }
    /
  • 函数名称:void SCCB_Star(void)
  • 功能说明:启动函数
    /
    void SCCB_Star(void)
    {
    SCL_Out;
    SDA_Out;
    SCCB_Wait();
    SDA_High;
    SCL_High;
    SCCB_Wait();
    SDA_Low;
    SCCB_Wait();
    SCL_Low;
    SCCB_Wait();
    }
    /
  • 函数名称:void SCCB_Stop(void)
  • 功能说明:停止函数
    /
    void SCCB_Stop(void)
    {
    SCL_Out;
    SDA_Out;
    SCCB_Wait();
    SDA_Low;
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    SDA_High;
    SCCB_Wait();
    }
    /
  • 函数名称:uint8 SCCB_SendByte(uint8 Data)
  • 功能说明:SCCB发送字节函数
  • 参数说明:要发送的字节
  • 函数返回:应答信号
    **********/
    uint8_t SCCB_SendByte(uint8_t Data)
    {
    uint8_t i;Ack;
    SDA_Out;
    for( i=0; i<8; i++)
    {
    if(Data & 0x80) SDA_High;
    else SDA_Low;
    Data <<= 1;
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    SCL_Low;
    SCCB_Wait();
    }
    SDA_In;
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    Ack = SDA_Data;
    SCL_Low;
    SCCB_Wait();
    SDA_Out;
    return Ack;
    }
    /
  • 函数名称:uint8 SCCB_ReadByte(void)
  • 功能说明:SCCB读取字节函数 :
    /
    uint8_t SCCB_ReadByte(void)
    {
    uint8_t i;
    uint8_t byte = 0;
    SCL_Out;
    SDA_In; //使能输入
    for( i=0; i<8; i++)
    {
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    byte = byte<<1;
    if(SDA_Data)
    byte++;
    SCCB_Wait();
    SCL_Low;
    }
    SDA_Out;
    SCCB_Wait();
    return byte; }
    /
  • 函数名称:static void SCCB_Ack(void)
  • 功能说明:IIC有回复信号
    /
    static void SCCB_Ack(void)
    {
    SCL_Out;
    SDA_Out;
    SCL_Low;
    SDA_Low;
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    SCL_Low;
    SCCB_Wait();
    }
    /
  • 函数名称:static void SCCB_NAck(void)
  • 功能说明:IIC无回复信号
    ***************************************************************/
    static void SCCB_NAck(void)
    {
    SCL_Out;
    SDA_Out;
    SCL_Low;
    SCCB_Wait();
    SDA_High;
    SCCB_Wait();
    SCL_High;
    SCCB_Wait();
    SCL_Low;
    SCCB_Wait();
    }

/*************************************************************************

  • 函数名称:void SCCB_RegWrite(uint8 Device,uint8 Address,uint16 Data)

  • 功能说明:向设备写数据

  • 参数说明:要发送的字节

  • 函数返回:应答信号
    ************************************************************/
    uint8_t SCCB_RegWrite(uint8 Device,uint8 Address,uint8_t Data)
    {
    uint8_t Ack = 0;

    SCCB_Star();
    Ack = SCCB_SendByte(Device<<1);

    Ack = SCCB_SendByte(Address);

    Ack = SCCB_SendByte(Data);

    SCCB_Stop();
    return Ack;
    }
    /***************************************************************

  • 函数名称:uint8_t SCB_RegRead(uint8_t Device,uint8_t Address,uint16_t *Data)

  • 功能说明:读取数据
    ***************************************************************/
    uint8_t SCCB_RegRead(uint8_t Device,uint8_t Address,uint8_t *Data)
    {
    uint8 Ack = 0;
    Device = Device<<1;
    SCCB_Star();
    Ack += SCCB_SendByte(Device);
    SCCB_Wait();
    Ack += SCCB_SendByte(Address);
    SCCB_Wait();
    SCCB_Stop();
    SCCB_Wait();
    SCCB_Star();
    Ack += SCCB_SendByte(Device | 0x01);

    *Data = SCCB_ReadByte();
    SCCB_NAck();
    SCCB_Stop();
    return Ack;
    }

/***************************************************************

  • 函数名称:int SCCB_Probe(uint8_t chipAddr)

  • 功能说明:查询该地址的设备是否存在
    ***************************************************************/
    int SCCB_Probe(uint8_t chipAddr)
    {
    uint8_t err;
    err = 0;
    chipAddr <<= 1;

    SCCB_Star();
    err = SCCB_SendByte(chipAddr);
    SCCB_Stop();

    return err;
    }

/***************************************************************
//初始化各个通道PWM
***************************************************************/
void Motor_Init(void)
{
//舵机频率:90M/(2^5)/56250=50HZ,
//电机频率:90M/(2^5)/ 1000=2.8kHZ,
FTM_PWM_Init(FTM0,FTM_CH0,1000, 500);//Mot0-PTC1
FTM_PWM_Init(FTM0,FTM_CH1,1000, 500);//Mot1-PTC2
FTM_PWM_Init(FTM0,FTM_CH2,1000, 500);//Mot2-PTC1
FTM_PWM_Init(FTM0,FTM_CH3,1000, 500);//Mot3-PTC2

FTM_PWM_Init(FTM2,FTM_CH1,56250,Step_Middle);//Mot11-PTB19 舵机方向左边大右边小
}
//1号马达驱动函数
void Motor_Run_1(u16 fb, u16 duty)
{
if(fb) //1,前进
{
Motor_Duty(Mot0, 0);
Motor_Duty(Mot1,duty);
}
else //0,后退
{
Motor_Duty(Mot0, duty);
Motor_Duty(Mot1, 0);
}
}
//2号马达驱动函数
void Motor_Run_2(u16 fb, u16 duty)
{
if(fb) //1,前进
{
Motor_Duty(Mot2, 0);
Motor_Duty(Mot3,duty);
}
else //0,后退
{
Motor_Duty(Mot2, duty);
Motor_Duty(Mot3, 0);
}
}

//马达驱动子函数
void Motor_Ctrl(u16 duty)
{
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH0) = duty;
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH1) = 500;
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH2) = duty;
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH3) = 500;
}

// PWM通道占空比设置–用于电机设置
/switch(表达式){
case 常量表达式1: 语句 1;
case 常量表达式2: 语句 2;

case 常量表达式n: 语句 n;
default: 语句 n+1;break
}
它的执行过程是:首先计算“表达式”的值,然后从第一个 case 开始,
与“常量表达式x”进行比较,如果与当前常量表达式的值不相等,那么就不执行冒号后边的语句 x,
一旦发现和某个常量表达式的值相等了,那么它会执行之后所有的语句,
如果直到最后一个“常量表达式 n”都没有找到相等的值,那么就执行 default 后的“语句 n+1”。
/
void Motor_Duty(u16 Motno, u16 duty)
{
//if(duty<3001)
{
switch(Motno)
{
case Mot0:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH0) = duty;
break;

    case Mot1:FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH1) = duty;break;case Mot2:FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH2) = duty;break;case Mot3:FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH3) = duty;break;       default:break; }
}

}

// PWM通道占空比设置–用于舵机控制
void Servo_Duty(u16 Motno, u16 duty)
{
{
switch(Motno) {
case Mot0:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH0) = duty;
break;
case Mot1:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH1) = duty;
break;
case Mot2:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH2) = duty;
break;
case Mot3:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH3) = duty;
break;
case Mot4:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH4) = duty;
break;
case Mot5:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH5) = duty;
break;
case Mot6:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH6) = duty;
break;
case Mot7:
FTM_CnV_REG(FTM0_BASE_PTR, FTM_CH7) = duty;
break;
case Mot8:
FTM_CnV_REG(FTM1_BASE_PTR, FTM_CH0) = duty;
break;
case Mot9:
FTM_CnV_REG(FTM1_BASE_PTR, FTM_CH1) = duty;
break;
case Mot10:
FTM_CnV_REG(FTM2_BASE_PTR, FTM_CH0) = duty;
break;
case Mot11:
FTM_CnV_REG(FTM2_BASE_PTR, FTM_CH1) = duty;
break;
default:
break;
}
}
}

/------------------------------------------------------------------------------------------------------
【函 数】Ultrasonic_Init
HC_TRIG PTE9 //驱动发射信号引脚
HC_ECHO PTE10 //输出高电平引脚
--------------------------------------------------------------------------------------------------------
/
Ultrasonic_Init(void)
{
GPIO_Init(PORTE,9,GPO, 0);
GPIO_Init(PORTE,10,GPI, 0);
}

/*************************************************************************

  • 函数名称:Get_Use_Image
  • 功能说明:摄像头原始帧120320像素压缩为60100像素图像
    *************************************************************************/
    void Get_Use_Image(void)
    {
    int i = 0,j = 0,row = 0,line = 0;

for(i = 0; i <ROWS; i +=120/60) //IMAGEH / div = LCDH
{
for(j = 0; j <240; j += 8) //IMAGEW / div = LCDW
{
Image_Use[row][line] = Image_Data[i][j];
line++;
Image_Use[row][line] = Image_Data[i][j+1];
line++;

}
for(j = 240; j <400; j += 4)   //IMAGEW / div  = LCDW
{        Image_Use[row][line] = Image_Data[i][j];         line++;    Image_Use[row][line] = Image_Data[i][j+1];         line++; }
for(j = 400; j <640; j += 8)   //IMAGEW / div  = LCDW
{        Image_Use[row][line] = Image_Data[i][j];         line++;    Image_Use[row][line] = Image_Data[i][j+1];         line++; }      line = 0;
row++;

}
OK_Flag = 1;
}

/*************************************************************************

  • 函数名称:Draw_change(bmp[][])
  • 功能说明:摄像头数据2维矩阵数组 转化为 OLED屏幕1维16进制数组
  • 参数说明:无
  • 函数返回:无
  • 备 注:
    *************************************************************************/
    void Draw_change(u8 bmp01[][200])
    {
    int i,j;

for(i=0;i<60;i++)
{
// j=(i-B)/K;
// if(j>=0&&j<=100)
// bmp01[i][j]=0xff;
// bmp01[i][Line_Center[i]] =0x55;
for(j=0;j<100;j++)
{

//Image_change[i200+j2]=bmp01[i][j];
// Image_change[i200+j2+1]=bmp01[i][j];

Image_change[i200+j2]=bmp01[i][j2];
Image_change[i
200+j2+1]=bmp01[i][j2+1];

}
}
}

/*************************************************************************

  • 函数名称:Line_trace;
  • 功能说明:智能车寻线行驶子程序
    *************************************************************************/
    void Line_trace(void)
    {
    RGB_Change(Image_Use);
    GetOSTU(Pixle_RGB[60][100]);
    Pixle_Filter(Pixle[60][100]);
    K_B(Center);
    Turn_control();
    }

/------------------------------------------------------------------------------------------------------
【函 数】Test_HCSR04
【功 能】超声波侧距离函数
HC_TRIG PTE9 //驱动发射信号引脚
HC_ECHO PTE10 //输出高电平引脚
--------------------------------------------------------------------------------------------------------
/
float Test_HCSR(void)
{
int num=0 ;
float dis=0;

GPIO_Ctrl (PORTE,9,1);
LPTMR_delay_us(10);
GPIO_Ctrl (PORTE,9,0);

/* 超声波模块开始发送超声波 */
while(!GPIO_Get(PTE10));
LPTMR_time_start_us();
while(GPIO_Get(PTE10)) ;
num = LPTMR_time_get_us();

dis = (float)num * 0.017; //计算距离dis
return dis;
}

/------------------------------------------------------------------------------------------------------
【函 数】Traffic_watch
【功 能】红绿灯及左右转弯标志识别
--------------------------------------------------------------------------------------------------------
/
void Traffic_watch (void)
{
int i,j;
turn_up_down=0;
turn_left_right=0;
stop_car=0;
light_i=0;
light_j=0;
for(j=0;j<100;j++)
center[j]=0;
for(i=0;i<60;i++)
for(j=0;j<100;j++)
{
Pixle_R[i][j]=(Image_Use[i][2j]&0xf8)>>3;
Pixle_G[i][j]=((Image_Use[i][2
j]&0x07)<<3)+((Image_Use[i][2j+1]&0xe0)>>5);
Pixle_B[i][j]=Image_Use[i][2
j+1]&0x1f;
Pixle_RGB[i][j]=Pixle_R[i][j]+Pixle_G[i][j]+Pixle_B[i][j];

}

for(i=5;i<55;i++)
{
for(j=10;j<90;j++)
{
if((Pixle_RGB[i][j+1]-Pixle_RGB[i][j]>80)&&(Pixle_RGB[i][j+2]-Pixle_RGB[i][j]>80)&&(Pixle_R[i][j]-Pixle_G[i][j]>5))
{
stop_car=1;
light_i=i;
light_j=j;
i=60;
j=98;
}

}

}

for(i=0;i<60;i++)
{
for(j=0;j<100;j++)
{
if(Pixle_B[i][j]+Pixle_R[i][j]>50)
Pixle_R[i][j]=1;
else
Pixle_R[i][j]=0;
}
}
for(i=0;i<60;i++)
{
for(j=0;j<100;j++)
{
if(Pixle_R[i][j]==1&&Pixle_R[i+1][j]+Pixle_R[i-1][j]+Pixle_R[i][j+1]+Pixle_R[i][j-1]<=1)
Pixle_R[i][j]=0;

}
}
for(j=0;j<100;j++)
for(i=5;i<55;i++)
center[j]=center[j]+Pixle_R[i][j];

for(j=2;j<95;j++)
{
if(center[j]+center[j+1]+center[j+2]>75&&(center[j+2]-center[j]>=-3&&center[j+2]-center[j]<=3)&&(center[j+2]-center[j+4]>10||center[j]-center[j-2]>10)&&(center[j+2]-center[j+4]<30||center[j]-center[j-2]<30))
turn_up_down=j;
}

for(j=0;j<96;j++)
{
if(center[j]>4&&center[j]<=13&&center[j+1]>4&&center[j+1]<=13&&center[j+2]>4&&center[j+2]<=13&&center[j+3]>4&&center[j+3]<=13&&center[j+4]>4&&center[j+4]<=13)
turn_left_right=j;
}

if(turn_up_down0||turn_left_right0)
turn_car=0;
else if(turn_up_down<turn_left_right-1)
turn_car=1; //左转
else if(turn_up_down>turn_left_right+1)
turn_car=2; //右转
else
turn_car=0;

}

基于恩智浦MK60DN512Z系列单片机的智能模型车主程序与子程序集相关推荐

  1. STC51系列单片机不断电自动下载程序

    以前在进行单片机编程时比较烦恼的时每次下载程序都需要断电,点击下载,再上电才能将程序下载到单片机,如果偶尔一两次这样操作可以忍受,但是往往我们都是需要调试代码,多次进行下载操作,不断的断电上电无疑对单 ...

  2. 飞思卡尔MKL系列单片机用jlink烧写程序出现的Kinetis (connect): Timeout while halting CPU. CPU does not stop.问题

    最近用Jlink烧写飞思卡尔MKL16Z128单片机时发现经常出现不能连接成功的情况,用的是SWD接口,排查了好久后来发现问题在单片机的RESET脚上,因为之前用SWD接口的时候只接4线(SWD.SC ...

  3. 基于STM32单片机的智能停车场车位管理系统设计

    摘  要 通过调查发现,现有的许多公共场所的停车位管理落后,智能化程度不高.为顺应现代自动化狂潮的发展趋势,本项目以STM32单片机为主控芯片,基于RFID智能识别技术,设计了一个具有IC识别的智能停 ...

  4. STC系列单片机内部EEPROM 测试程序

    硬件电路: P1口接8个LED到VCC. 适用硬件: STC12C2052系列(杜洋工作室改进部分) STC12C5AxxAD系列单片机 STC12C52xxAD系列单片机 STC11xx系列单片机 ...

  5. 主题:瑞萨16 位R8C/TINY 系列单片机

    主题:瑞萨16 位R8C/TINY 系列单片机– 小型,少脚数,高速,高效能,含闪存的MCU 在线问答: [问:winalltech] WDT通过软件来开关,有可能不可靠吗?会因为干扰而造成其突然关闭 ...

  6. 瑞萨16 位R8C/TINY 系列单片机

    主题:瑞萨16 位R8C/TINY 系列单片机– 小型,少脚数,高速,高效能,含闪存的MCU 在线问答: [问:winalltech] WDT通过软件来开关,有可能不可靠吗?会因为干扰而造成其突然关闭 ...

  7. 基于Java毕业设计幼儿影视节目智能推荐系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计幼儿影视节目智能推荐系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计幼儿影视节目智能推荐系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构 ...

  8. 计算机毕业设计ssm基于SSM的美妆分享网站vf952系统+程序+源码+lw+远程部署

    计算机毕业设计ssm基于SSM的美妆分享网站vf952系统+程序+源码+lw+远程部署 计算机毕业设计ssm基于SSM的美妆分享网站vf952系统+程序+源码+lw+远程部署 本源码技术栈: 项目架构 ...

  9. 鸿蒙51单片机,基于C51系列单片机的交通控制系统设计

    2.2 数码时间显示电路 七段LED数码管是由八个发光二极管构成,通过给其引脚不同的高低电平,从而显出0~9的数字和小数点,本文通过四个一位数码管并联通过P3口当中的P3.0与P3.1与STATIC ...

最新文章

  1. Emlog文章特色图生成插件分享
  2. CString Format 乱码问题
  3. sql 查询的在northern最大的价值(LAT_N),小于137.2345 ,在小数点后4 位截断
  4. xbox360 ubuntu14.04连接问题
  5. Web前端开发解耦1
  6. HRESULT:0x80040228 异常解决
  7. C++_弱引用 强引用_weak_ptr/share_ptr
  8. 将页面强制保持在所属框架中
  9. 汉字--拼音--网页汉字转拼音--包教包会
  10. 用JavaScript做一个日历和用canvas做一个时钟
  11. Ubuntu 重置密码
  12. c语言的Hello World
  13. 假设检验与常见的统计检验方法
  14. Java程序设计实验(二):类的创建和封装实验
  15. The vulnerabilities were addressed in OpenSSL 1.02f/1.01r. cocos2d 2.2.6
  16. java socket 拒绝链接_ConnectException:连接被拒绝
  17. jq 之 download下载图片或文件功能,以及一个神奇的download属性!
  18. 下列不属于噪声的是_[单选] 下列选项中不属于噪声的是()。
  19. 【MySQL】警告: 1681 - XXX is deprecated and will be removed in a future release.
  20. 1.[RK3288][Android6.0] USB UVC 协议简结

热门文章

  1. Python基于PHP+MySQL的个人网页设计与实现
  2. C++ 中transform方法的疑惑和自己的感受
  3. 异步赠书:12月《Go Web编程》领航
  4. Excel如何利用函数删除数据中空格
  5. ViewPager中呈现前一页和后一页的内容
  6. .dwg(sw)-exb
  7. 汉字进行计算机识别的原理,计算机OCR文字识别技术的原理和未来发展趋势
  8. CentOS 官网镜像最新下载地址
  9. 无法打开**,因为此版本的应用程序不支持其项目类型(.vcproj)
  10. java获取显示器屏幕大小