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

📄 cam.c

📁 基于单片机的串口摄像头模块的读写C语言源程序
💻 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 + -