
#include <reg51h>
#define uchar unsigned char //定义unsigned int为uint
#define uint unsigned int //定义unsigned uchar为uchar
sbit LCD_RS = P2^0 ;
sbit LCD_RW = P2^1 ;
sbit LCD_EN = P2^2 ;
sbit D_SDA = P2^6; //定义74HC164数据线为P26端口
sbit D_SCL = P2^7; //定义74HC164数据线为P27端口
sbit CLK = P1^3; /实时时钟时钟线引脚 /
sbit IO = P1^4; /实时时钟数据线引脚 /
sbit RST = P1^5; /实时时钟复位线引脚 /
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
uchar time[8] = {0x50,0x30,0x19,0x30,0x12,0x06,0x06};
//========= 延时函数 ============
//延时时间以1ms为单位
//s决定延时时间长短
void delay_ms(uint s)
{
uint x;
for(s;s>0;s--)
{
x = 200;
while(x--);
}
}
//========= 送出一个字节给74HC164(实现串并转换) ==========
void send_out(unsigned char out)//传送一个字节8位
{
uchar i;
D_SCL = 0;
for (i=8;i>=1;i--)
{
D_SDA = out&0x80; //送数据到数据口
D_SCL = 1; //时钟线置1
D_SCL = 0; //送一时钟
out<<=1; //左移
}
}
//========= 写命令函数 ==========
void lcd_wcmd(uchar cmd)
{
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
send_out(cmd);
LCD_EN = 1;
LCD_EN = 0 ;
}
//========= 写数据函数 ==========
void lcd_wdat(uchar dat)
{
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
send_out(dat);
LCD_EN = 1;
LCD_EN = 0;
}
//========= LCD初始化函数 ==========
void lcd_init()
{
lcd_wcmd(0x38);
delay_ms(1);
lcd_wcmd(0x0c); //显示开,关光标
delay_ms(1);
lcd_wcmd(0x06); //向右移动光标
delay_ms(1);
lcd_wcmd(0x01); //清除LCD显示屏
delay_ms(1);
}
//========== 往DS1302写入1Byte数据 (内部函数) =============
void w_byte(uchar dat)
{
uchar i;
for(i=8; i>0; i--)
{
IO = dat & 0x01;
CLK = 1;
CLK = 0;
dat = dat >> 1;
}
}
//======== 从DS1302读取1Byte数据 (内部函数) ===================
uchar r_byte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >> 1;
ACC7 = IO;
CLK = 1;
CLK = 0;
}
return(ACC);
}
//========== 指定地址往DS1302写入1Byte数据 (内部函数) =============
void write_byte(uchar addr, uchar dat)
{
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
w_byte(dat);
CLK = 1;
RST = 0;
}
//========== 指定地址往DS1302读1Byte数据 (内部函数) =============
uchar read_byte(uchar addr)
{
uchar ucData;
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
ucData = r_byte();
CLK = 1;
RST = 0;
return(ucData);
}
//============ 设置ds1302日期和时间 =============
void write_ds1302(uchar p)
{
uchar i;
uchar addr = 0x80;
write_byte(0x8e,0x00); // 控制命令,WP=0,写 *** 作
for(i =7; i>0; i--)
{
write_byte(addr,p); // 秒 分 时 日 月 星期 年
p++;
addr +=2;
}
write_byte(0x8e,0x80); // 控制命令,WP=1,写保护
}
//============ 读ds1302当前日期和时间 =============
void read_ds1302(uchar p)
{
uchar i;
uchar addr = 0x81;
for (i=0; i<7; i++)
{
p = read_byte(addr); //格式为: 秒 分 时 日 月 星期 年
addr += 2;
p++;
}
}
//============ 显示函数 ===================
void lcd_disp()
{
uchar addr = 4;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[2]>>4)&0x0f)+0x30); //显示小时
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[2]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //显示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[1]>>4)&0x0f)+0x30); //显示分
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[1]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //显示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[0]>>4)&0x0f)+0x30); //显示秒
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[0]&0x0f)+0x30);
addr = 2;
lcd_wcmd(0xc0 + addr); //在第二行显示年月日和星期
lcd_wdat('2'); //显示2
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat('0'); //显示0
addr++;
lcd_wdat(((time[6]>>4)&0x0f)+0x30); //年
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[6]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[4]>>4)&0x0f)+0x30); //显示月
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[4]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[3]>>4)&0x0f)+0x30); //显示日
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[3]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[5]&0x0f)+0x30); //显示星期
}
//=========== 主函数 ===============
void main()
{
lcd_init(); // 初始化LCD
write_ds1302(time);
while(1)
{
read_ds1302(time); //读DS1302数据
lcd_disp(); //LCD显示
delay_ms(500); //延时05秒
}
}
这是一个电子时钟,在LCD1602上显示,时钟芯片是DS1302
以下是四位数码管可调时带秒闪烁的c51单片机电子钟程序(c语言)。
/ 本程序中,晶振为12MHz, /
/ 时间控制采用定时中断控制方式。 /
/ 模式和时间调整采用查询方式。 /
#include<reg52h>
sbit P20=P2^0; //分个位控制端
sbit P21=P2^1; //分十位控制端
sbit P22=P2^2; //时个位控制端
sbit P23=P2^3; //时十位控制端
sbit led=P2^7; //second display led
sbit key0=P3^0; //模式设置
sbit key1=P3^1; //加
sbit key2=P3^2; //减
unsigned char hour,min,sec,T50ms;
unsigned char modstate; //模式状态
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//段码
void init(); //初始化子程序声明
void delay500us(unsigned char X); //延时子程序声明
void display(); //显示子程序声明
void display001(); //显示子程序声明
void display002(); //显示子程序声明
void keyscan(); //按键识别子程序声明
void main()
{
init();
while(1)
{
keyscan();
}
}
void init() //初始化子程序
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
ET0=1;
EA=1;
TR0=1;
}
void delay500us(unsigned char X)
{
unsigned char i,j;
for(i=X;i>0;i--)
for(j=248;j>0;j--);
}
void timer0() interrupt 1 //timer0中断服务子程序,定时时间为50ms,本程序加了10us的时间修正量
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
T50ms++;
if(T50ms>=20)
{
T50ms=0;
sec++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)hour=0;
}
}
}
}
void display()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(5);
if(T50ms<=10)led=0;
if(T50ms>10)led=1;
}
void display001()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(10);
}
void display002()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(10);
}
void keyscan() //按键识别钟程序
{
while(modstate==0)
{
display();
if(key0==0)
{
display();
if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display001(); //等待按键释放。
}
}
////
while(modstate==1)
{
display001();
if(key0==0)
{
display001();
if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display002(); //等待按键释放。
}
if(key1==0)
{
display001();
if(key1==0)
{
hour++;
if(hour>=24)hour=0;
while(key1==0)display001();
}
}
if(key2==0)
{
display001();
if(key2==0)
{
hour--;
if(hour>=24)hour=0;
while(key2==0)display001();
}
}
}
////
while(modstate==2)
{
display002();
if(key0==0)
{
display002();
if(key0==0)modstate=0; //这两句加在一起为延时10ms软件防抖设计。
while(key0==0)display(); //等待按键释放。
}
if(key1==0)
{
display002();
if(key1==0)
{
min++;
if(min>=60)min=0;
while(key1==0)display002();
}
}
if(key2==0)
{
display002();
if(key2==0)
{
min--;
if(min>=60)min=0;
while(key2==0)display002();
}
}
}
}
C51是基于标准的C语言扩展而来的,所以,标准C语言能做的东西,C51也可以。
平方运算,自不必说,就是两个数相乘:
例如:float a,b,c; c = ab;
开方,则需要用到库函数:
标准c语言里用的是 sqrt()函数,这个函数包含在mathh文件中。
所以:
#include <mathh>
c = sqrt(a);
就可以了
sbit dula=P2^6;//段锁存器锁存湍
sbit wela=P2^7;;//位锁存器锁存湍
char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
void display(shiwan_c,wan_c,qian_c,bai_c,shi_c,ge_c)//6位显示子程序
{
P0=table[shiwan_c]; //显示十万位
dula=1;
dula=0;
P0=0xfe;
wela=1;
wela=0;
delay(2);
P0=table[wan_c]; //显示万位
dula=1;
dula=0;
P0=0xfd;
wela=1;
wela=0;
delay(2);
P0=table[qian_c]; //显示千位
dula=1;
dula=0;
P0=0xfb;
wela=1;
wela=0;
delay(2);
P0=table[bai_c]; //显示百位
dula=1;
dula=0;
P0=0xf7;
wela=1;
wela=0;
delay(2);
P0=table[shi_c]; //显示十位
dula=1;
dula=0;
P0=0xef;
wela=1;
wela=0;
delay(2);
P0=table[ge_c]; //显示个位
dula=1;
dula=0;
P0=0xdf;
wela=1;
wela=0;
delay(2);
P0=0xff; //显示完毕后关闭最后一位显示
wela=1;
wela=0;
}
以上程序需放在循环程序中,数码管需反复显示
如果其中两位不需显示,可赋值为16
问题1)你所谓的同时工作是指led亮的同时数码管也在显示,是这样的吗?单片机跑的程序都是单线程的,所以函数可能会受到中断的影响
问题2)理论上,位选和段选是不要求顺序的,如果交换顺序会出现不一样的效果,说明你的程序写的有问题,根据你说的现象,我认为你段选和位选没设置好
#include<reg52h>
unsigned char code table[] ={" "};
unsigned char code table1[]={" : "};
sbit rs=P1^2;
sbit lcden=P1^0;
unsigned char flag,m;
void delay(int xms)
{
int i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void write_com(unsigned char com)
{//写液晶命令函数
rs=0;
lcden=0;
P2=com;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void write_date(unsigned char date)
{//写液晶数据函数
rs=1;
lcden=0;
P2=date;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void init()
{//初始化函数
unsigned char num;
lcden=0;
rs=0;
write_com(0x38);//1602液晶初始化
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)//写入液晶固定部分显示
{
write_date(table[num]);
delay(3);
}
write_com(0x80+0x40);
for(num=0;num<5;num++)
{
write_date(table1[num]);
delay(3);
}
}
void write_dianya(unsigned char add,unsigned char date)
{//1602液晶刷新时分秒函数4为时,7为分,10为秒
unsigned char bai,shi,ge;
bai=date/100;
shi=date%100/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+bai);
write_date(0x30+shi);
write_date(0x30+ge);
}
void main ()
{
init();
TMOD=0x20; //设置定时器1工作方式2
TH1=0xfd;
TL1=0xfd;
TR1=1;
REN=1; //设置串行口工作方式
SM0=0;
SM1=1;
EA=1; //中断设置
ES=1;
while(1)
{
if(flag==1)
{
ES=0;
SBUF=m;
while(!TI);
TI=0;
ES=1;
}
}
}
void ser() interrupt 4
{
RI=0;
m=SBUF;
write_dianya(5,m);
flag=1;
}
以上就是关于求c51单片机电子钟程序(c语言)全部的内容,包括:求c51单片机电子钟程序(c语言)、51单片机求这个时钟的c语言程序、C51单片机怎么用C语言实现数值的开方和平方运算等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)