这是当时我的第一个51练手作品,现在看来有不少地方写的很繁琐,发着玩,求轻喷[s::)]
快门线,输入间隔时间和拍摄张数就可以控制单反间隔拍摄了,详情见某宝,一搜一大把[s::)]
硬件连接很简单,单片机12c2052ad,液晶是1602a
#include<stc12c2052ad.h>
#define uchar unsigned char
#define uint unsigned int
#define lcd P1//lcd数据
void busytest();
void lcd_com(uchar com);
void lcd_data(uchar date);
void lcdinit();
void timeset();
void times();
void delay(uint t);
void interrupt_init();
void shooting();
void beef();//蜂鸣器,io口不够用,没加。。。
sbit lcdrs = P3 ^ 4;
sbit lcdrw = P3 ^ 3;
sbit lcden = P3 ^ 7;
sbit lcdbusy = P1 ^ 7; //busy test port,same as D7
sbit key1=P3^0;//百位输入
sbit key2=P3^1;//十位输入
sbit key4=P3^2;//ok键,可中断
sbit key3=P3^5;//个位输入
sbit focus=P3^0;//对焦继电器
sbit shoot=P3^1;//拍摄继电器
sbit beefer=P3^5;
uint ctime;
uchar bai;
uchar shi;
uchar ge;
uint input_time;
uint input_shoots;
bit key4press;
uint tnum;//时间计数
uint snum;//次数计数
bit timefull;
uchar printnum1;
uchar printnum2;
uchar printnum3;
uchar printnum4;
uchar printnum5;
uchar printnum6;
uchar printnum7;
uchar code table[]="PLEASE SET TIME"; //15
uchar code table1[]="time(s):"; //8
uchar code table2[]="01234567890";
uchar code table3[]="SET SHOOT TIMES"; //15
uchar code table4[]="PRESS OK TO"; //11
uchar code table5[]="START"; //5
uchar code table6[]="REST TIME:";//10
uchar code table7[]="REST SHOOTS:"; //12
/***************************************************************************/
#define CMD_clear 0x01 // 清除屏幕
#define CMD_back 0x02 // DDRAM回零位
#define CMD_dec1 0x04 // 读入后AC(指针)减1,向左写
#define CMD_add1 0x06 // 读入后AC(指针)加1,向右写
#define CMD_dis_gb1 0x0f // 开显示_开光标_开光标闪烁
#define CMD_dis_gb2 0x0e // 开显示_开光标_关光标闪烁
#define CMD_dis_gb3 0x0c // 开显示_关光标_关光标闪烁
#define CMD_OFF_dis 0x08 // 关显示_关光标_关光标闪烁
#define CMD_set82 0x38 // 8位总线_2行显示
#define CMD_set81 0x30 // 8位总线_1行显示(上边行)
#define CMD_set42 0x28 // 4位总线_2行显示
#define CMD_set41 0x20 // 4位总线_1行显示(上边行)
#define lin_1 0x80 // 4位总线_1行显示(上边行)
#define lin_2 0xc0 // 4位总线_1行显示(上边行)
/***************************************************************************/
void main()
{
lcdinit();
interrupt_init();
focus=1;
shoot=1;
for(printnum1=0;printnum1<15;printnum1++)
lcd_data(table[printnum1]);
lcd_com(0x80+0x40); //换行
for(printnum2=0;printnum2<8;printnum2++)
lcd_data(table1[printnum2]);
timeset();
key4press=0;
lcd_com(CMD_clear);
input_time=(bai*100+shi*10+ge)*2;//单位50ms
ctime=(bai*100+shi*10+ge)/10;
bai=0;
shi=0;
ge=0;
for(printnum3=0;printnum3<15;printnum3++)
lcd_data(table3[printnum3]);
lcd_com(0x80+0x40);
times();
input_shoots=bai*100+shi*10+ge;//拍摄次数
lcd_com(CMD_clear);
key4press=0;
for(printnum4=0;printnum4<11;printnum4++)
lcd_data(table4[printnum4]);
lcd_com(0x80+0x40);
for(printnum5=0;printnum5<5;printnum5++)
lcd_data(table5[printnum5]);
while(key4press==0);//等待ok按下
lcd_com(CMD_clear);
shooting();
lcd_com(CMD_clear);
lcd_data('F');
lcd_data('I');
lcd_data('N');
lcd_data('I');
lcd_data('S');
lcd_data('H');
lcd_data('!');
//beef();//未实现
while(1);
}
void busytest()
{
lcd = 0xff; //测忙函数
lcdrs = 0;
lcdrw = 1;
lcden = 1;
while(lcdbusy);
lcden = 0;
}
void lcd_com(uchar com) //写命令
{
busytest();
lcd = com;
lcdrs = 0;
lcdrw = 0;
lcden = 1;
lcden = 0;
}
void lcd_data(uchar date) //写数据
{
busytest();
lcd = date;
lcdrs = 1;
lcdrw = 0;
lcden = 1;
lcden = 0;
}
void lcdinit()
{
lcd_com(CMD_set82); // 显示模式设置:显示2行,每个字符为5*7个像素
lcd_com(CMD_clear); // 显示清屏
lcd_com(CMD_back); // 数据指针指向第1行第1个字符位置
lcd_com(CMD_add1); // 显示光标移动设置:文字不动,光标右移
lcd_com(CMD_dis_gb3); // 显示开及光标设置:显示开,光标开,闪烁开
}
void delay(uint t)
{
uint b,c;
for(b=0;b<t;b++)
for(c=0;c<355;c++);
}
void timeset()
{
while(key4press==0)
{
if(key1==0)
{
delay(10);
if(key1==0)
{
bai++;
}
while(key1==0);
}
if(key2==0)
{
delay(10);
if(key2==0)
{
shi++;
}
while(key2==0);
}
if(key3==0)
{
delay(10);
if(key3==0)
{
ge++;
}
while(key3==0);
}
if(bai==10)
bai=0;
if(shi==10)
shi=0;
if(ge==10)
ge=0;
lcd_com(0x80+0x40+0x08);//指针控制
lcd_data(table2[bai]);
lcd_data(table2[shi]);
lcd_data('.');
lcd_data(table2[ge]);
}
}
void times()
{
while(key4press==0)
{
if(key1==0)
{
delay(10);
if(key1==0)
{
bai++;
}
while(key1==0);
}
if(key2==0)
{
delay(10);
if(key2==0)
{
shi++;
}
while(key2==0);
}
if(key3==0)
{
delay(10);
if(key3==0)
{
ge++;
}
while(key3==0);
}
if(bai==10)
bai=0;
if(shi==10)
shi=0;
if(ge==10)
ge=0;
lcd_com(0x80+0x40);//指针控制
lcd_data(table2[bai]);
lcd_data(table2[shi]);
lcd_data(table2[ge]);
lcd_data(' ');
lcd_data('s');
lcd_data('h');
lcd_data('o');
lcd_data('o');
lcd_data('t');
lcd_data('s');
}
}
void timer0() interrupt 1
{
TH0=0x3c;//初装,50ms
TL0=0xb0;
tnum++;
if(tnum==input_time/2)
{
timefull=1;
tnum=0;
}
}
void interrupt_init()
{
TMOD=0x01;//定时器模式设置
//AUXR &= 0x7F;//定时器时钟12T模式
TH0=0x3c;//初装,50ms
TL0=0xb0;
ET0=1;//开定时器中断
EA=1; //开总中断
//TR0=1;//开定时器
//P2M1=0;
//P2M0=0xFF;
EX0=1;//开外部中断0
IT0=1;//外部中断0设为下降沿触发
}
void shooting()
{
TR0=1;
while(snum<input_shoots)
{
for(printnum6=0;printnum6<10;printnum6++)
lcd_data(table6[printnum6]);
lcd_data(table2[(input_shoots-snum)*ctime /60 / 100]);
lcd_data(table2[(input_shoots-snum)*ctime /60 % 100 / 10]);
lcd_data(table2[(input_shoots-snum)*ctime /60 % 10]);
lcd_data('m');
lcd_data('i');
lcd_data('n');
lcd_com(0x80+0x40);
for(printnum7=0;printnum7<12;printnum7++)
lcd_data(table7[printnum7]);
lcd_data(table2[(input_shoots-snum)/100]);
lcd_data(table2[((input_shoots-snum)%100)/10]);
lcd_data(table2[(input_shoots-snum)%10]);
focus=0;
while(timefull==0);//等待定时器满
timefull=0;
shoot=0;
delay(50);
focus=1;
shoot=1;
while(timefull==0);//等待定时器满
timefull=0;
snum++;
lcd_com(CMD_clear);
}
}
void beef()
{
unsigned int c,d,e;
while(e<20)
{
while(d<3000)
{
beefer=~beefer;
for(c=0;c<100;c++);
d++;
}
d=0;
delay(500);
e++;
}
}
void key4scan() interrupt 0
{
if(key4==0)
{
delay(10);
if(key4==0)
key4press=1;
while(key4==0);
}
}
200字以内,仅用于支线交流,主线讨论请采用回复功能。