📄 cam.c
字号:
#include <SST89x5xxRD2.h>
#define uchar unsigned char
#define uint unsigned int
#define Width 10 //图像的宽80(8*10)个像素
#define Height 32 //图像的高
uchar lcd_x;//lcd的x坐标
uchar lcd_y;//lcd的y坐标
sbit cs=P3^3; //定义LCD的D/#C控制口
sbit std=P3^5; //定义LCD的串行数据端口
sbit sclk=P3^7; //定义LCD的串行时钟端口
sbit rst=P3^6;
sbit key=P2^0;
uchar code SYNC_ID[]= {0xaa,0x0d,0x00,0x00,0x00,0x00};
uchar code INITAL_ID[]= {0xaa,0x01,0x00,0x01,0x01,0x01}; //2位灰度图160*120,4800B
uchar code BAUDRATE_ID[]= {0xaa,0x07,0xbf,0x01,0x00,0x00}; //baudrate=9600
uchar code SNAPSHOT_ID[]= {0xaa,0x05,0x01,0x00,0x00,0x00};
uchar code GETPICTURE_ID[]= {0xaa,0x04,0x01,0x00,0x00,0x00};
uchar code RESET1_ID[]= {0xaa,0x08,0x01,0x00,0x00,0x00};//状态寄存器复位
uchar code RESET2_ID[]= {0xaa,0x08,0x00,0x00,0x00,0x00};//完全复位
uchar code SLEEP_ID[]= {0xaa,0x09,0x00,0x00,0x00,0x00};
uchar code ACK1_ID[]= {0xaa,0x0e,0x0d,0x00,0x00,0x00};
uchar code ACK2_ID[]= {0xaa,0x0e,0x0a,0x00,0x00,0x00};
//定义两个队列用来缓存图片数据
uchar xdata Picture_Dat1[256]; //内部扩展数据RAM(00H~2FFH)
uchar xdata Picture_Dat2[256];
uchar idata front=0,rear=0;//队列的队头指针和队尾指针
bit bank;//bank=0指向Picture_Dat1,否则指向Picture_Dat2
uint idata countr;//已接受的数据(byte)
bit error;//传输出错
void delay(uchar mm)
{
uchar idata i;
for(i=0;i<mm;i++)
;
}
void delay_1ms()
{
uchar idata i;
for(i=0;i<255;i++)
;
for(i=0;i<42;i++)
;
}
void delay_ms(uchar t)
{
uchar idata i;
for(i=0;i<t;i++)
delay_1ms();
}
void wr_lcd (uchar dat_comm,uchar content)
{
uchar idata a,i,j;
delay(50);
a=content;
cs=1;
sclk=0;
std=1;
for(i=0;i<5;i++)
{
sclk=1;
sclk=0;
}
std=0;
sclk=1;
sclk=0;
if(dat_comm)
std=1;//data
else
std=0;//command
sclk=1;
sclk=0;
std=0;
sclk=1;
sclk=0;
for(j=0;j<2;j++)
{
for(i=0;i<4;i++)
{
a=a<<1;
std=CY;
sclk=1;
sclk=0;
}
std=0;
for(i=0;i<4;i++)
{
sclk=1;
sclk=0;
}
}
}
void init_lcd (void)
{
rst=0;
delay(100);
rst=1;
wr_lcd(0,0x30); //30---基本指令动作
wr_lcd(0,0x01); //清屏,地址指针指向00H
delay(100);
wr_lcd(0,0x06); //光标的移动方向
wr_lcd(0,0x0c); //开显示,关游标
}
//1、换晶振,用22.1184M晶振,在TH1=0xff时,刚好可以产生115200波特率。
//2、采用6个时钟周期的单片机(换单片机啊。。。)
//3、增强型51单片机有定时器2!(幸好偶用的是增强型。。。)
//就用第三种方法啦!这时的公式如下:
//波特率=11059200/(32×[65536-(RCAP2H,RCAP2L)])
//其中的RCAP2H,RCAP2L为自动重装值,由上式得:
//RCAP2H,RCAP2L=65536-11059200/(32×波特率)
void init_UART()
{
SCON=0x50; //串口工作方式1,8位UART,波特率可变
TH2=0xFF;
TL2=0xDC; //波特率:9600 晶振=11.0592MHz
RCAP2H=0xFF;
RCAP2L=0xDC; //16位自动再装入值
//*****************
TCLK=1;
RCLK=1;
C_T2=0;
EXEN2=0; //波特率发生器工作方式
//*****************
ES=0;//关闭串口中断
EA=1;//开全局中断
TR2=1 ; //定时器2开始
}
void Read_Picture() interrupt 4 using 1
{
uchar dat;
if(RI)
{
dat=SBUF;
RI=0;
if(front==rear+1)//队列已满
{
ES=0;
error=1;
}
if(bank)
{
Picture_Dat2[rear]=dat;
bank=!bank;
rear++;
}
else
{
Picture_Dat2[rear]=dat;
bank=!bank;
countr++;
countr++;
}
}
}
void Send_Cmd(uchar *cmd)
{
uchar idata i;
for(i=0;i<6;i++)
{
SBUF=cmd[i];
while(TI==0)
;
TI=0;
delay(1);
}
}
void Wait_ACK(uchar *cmd)
{
uchar idata i;
for(i=0;i<6;i++)
{
while(RI==0)
;
cmd[i]=SBUF;
RI=0;
}
//if(cmd[0]==0xAA&&cmd[1]>=0x01&&cmd[1]<=0x0F)
// return 1;
//return 0;
}
bit CAM_Cmd(uchar *cmd)
{
uchar idata temp_cmd[6];
Send_Cmd(cmd);
Wait_ACK(temp_cmd);
if(temp_cmd[0]==0xAA&&temp_cmd[1]==0x0E&&temp_cmd[2]==cmd[1])
{
delay_ms(50);
return 1;
}
return 0;
}
bit Send_SYNC_Cmd()
{
uchar idata OldTH2,OldTL2;//保存原先的波特率
uchar idata cmd1[6];
uchar idata cmd2[6];
uchar idata i,j,k;
//*****************
//将波特率调整为115200
TR2=0 ; //定时器2停止
OldTH2=RCAP2H;
OldTL2=RCAP2L;
TH2=0xFF;
TL2=0xFD; //波特率:115200 晶振=11.0592MHz
RCAP2H=0xFF;
RCAP2L=0xFD; //16位自动再装入值
TR2=1 ; //定时器2开始
//*****************
for(i=0;i<60;i++)
{
Send_Cmd(SYNC_ID);
for(j=0;j<255;j++)
{
for(k=0;k<255;k++)
{
if(RI!=0)
{
Wait_ACK(cmd1);
Wait_ACK(cmd2);
break;
}
}
}
if(j==255&&k==255)//350ms内没有获得应答
continue;
if(cmd1[0]!=0xAA||cmd1[1]!=0x0E||cmd1[2]!=0x0D)
continue;
if(cmd2[0]!=0xAA||cmd2[1]!=0x0D)
continue;
Send_Cmd(ACK1_ID);
delay_ms(50);
break;
}
if(i==60)
return 0;
//将CAM的波特率设置为9600
CAM_Cmd(BAUDRATE_ID);
//*****************
//恢复原先波特率9600
TR2=0 ; //定时器2停止
TH2=OldTH2;
TL2=OldTL2;
RCAP2H=OldTH2;
RCAP2L=OldTL2; //16位自动再装入值
TR2=1 ; //定时器2开始
//*****************
return 1;
}
bit Get_Picture()
{
uchar idata temp_cmd[6];
uchar temp1,temp2,tempdat;
uchar i;
bank=0;
error=0;
countr=0;
lcd_x=0;
lcd_y=0;
wr_lcd (0,0x34);//8-BIT 控制接口的扩充指令集动作
wr_lcd(0,0x80); //设定GDRAM 地址到地址计数器
wr_lcd(0,0x81);
Send_Cmd(GETPICTURE_ID);
Wait_ACK(temp_cmd);
if(temp_cmd[2]==GETPICTURE_ID[1])
{
Wait_ACK(temp_cmd);
ES=1;
while(countr<1200&&(lcd_x<Width&&lcd_y<Height))
{
if(front!=rear)
{
temp1=Picture_Dat1[front];
temp2=Picture_Dat2[front];
front++;
tempdat=0;
for(i=0;i<4;i++)
{
tempdat<<=1;
if(temp1&0x80)
tempdat|=0x01;
temp1<<=2;
}
for(i=0;i<4;i++)
{
tempdat<<=1;
if(temp2&0x80)
tempdat|=0x01;
temp2<<=2;
}
wr_lcd(1,tempdat);
lcd_x++;
if(lcd_x==Width)//换行
{
lcd_y++;
wr_lcd (0,0x34);//8-BIT 控制接口的扩充指令集动作
wr_lcd(0,0x80+lcd_y); //设定GDRAM 地址到地址计数器
wr_lcd(0,0x81);
lcd_x=0;
}
}
else
{
if(error)
{
CAM_Cmd(RESET1_ID);
wr_lcd (0,0x36);
return 0;
}
}
}
ES=0;
if(countr<1200)
CAM_Cmd(RESET1_ID);
Send_Cmd(ACK2_ID);
wr_lcd (0,0x36);
delay_ms(50);
return 1;
}
return 0;
}
void main()
{
init_lcd();
init_UART();
wr_lcd (0,0x30);
wr_lcd (0,0x80);
wr_lcd (1,'S');
wr_lcd (1,'Y');
wr_lcd (1,'N');
wr_lcd (1,'C');
wr_lcd (1,' ');
if(Send_SYNC_Cmd())
{
wr_lcd (1,'O');
wr_lcd (1,'K');
}
else
{
wr_lcd (1,'E');
wr_lcd (1,'R');
goto ERROR;
}
wr_lcd (0,0x30);
wr_lcd (0,0x80);
wr_lcd (1,'I');
wr_lcd (1,'N');
wr_lcd (1,'I');
wr_lcd (1,'T');
wr_lcd (1,' ');
if(CAM_Cmd(INITAL_ID))
{
wr_lcd (1,'O');
wr_lcd (1,'K');
}
else
{
wr_lcd (1,'E');
wr_lcd (1,'R');
goto ERROR;
}
while(1)
{
if(!key)
{
delay_ms(10);
if(!key)
{
wr_lcd (0,0x30);
wr_lcd (0,0x85);
wr_lcd (1,'S');
wr_lcd (1,'N');
wr_lcd (1,'A');
wr_lcd (1,'P');
wr_lcd (1,' ');
wr_lcd (0,0x30);
wr_lcd (0,0x96);
if(CAM_Cmd(SNAPSHOT_ID))
{
wr_lcd (1,'O');
wr_lcd (1,'K');
}
else
{
wr_lcd (1,'E');
wr_lcd (1,'R');
goto ERROR;
}
Get_Picture();
while(!key)
;
}
}
}
ERROR:;
CAM_Cmd(RESET2_ID);
while(1)
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -