学单片机要学什么课程
给你两本书《爱上单片机》-作者杜洋
另外一本《单片机C语言程序设计实训100例基于8051+Proteus仿真》
留下QQ给你传一个PROTEUS仿真电路板,完全免费,不用买单片机学习板了。
QQ:794123566,非常感谢
本回答由提问者推荐
单片机课程设计(数字时钟) 麻烦大家不要发链接 直接帮我把程序写过来。
哈哈有个1602显示的不过程序太长贴不上给你个数码管的吧不行再联系
1302.c
#include
#include
ucharbit_ser[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
ucharseven_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/***********************时间显示*****************/
voidtimer0_init(void)//T0初始化函数,用于时间的动态显示
TMOD=0x21;
TL0=(65536-5000)%256;
TH0=(65536-5000)/256;
EA=1;
ET0=1;
TR0=1;
voidtimer0_isr(void)interrupt1//T0中断处理函数
charflag;//flag用于表示调整时闪烁的亮或灭
TR0=0;
TL0=(65536-5000)%256;
TH0=(65536-5000)/256;
TR0=1;
flag=x/100*0xff;//设置闪烁标志,如果x大于100则flag为0xff,小于100则为0x00
if(x>200)
switch(i)
case0:
P2=bit_ser[0];
if(setflag==3)//根据setflag的值判断当前位是否需要闪烁
P0=flag|seven_seg[dis_buffer[0]];
P0=seven_seg[dis_buffer[0]];
break;
case1:
P2=bit_ser[1];
if(setflag==3)
P0=flag|seven_seg[dis_buffer[1]];
P0=seven_seg[dis_buffer[1]];
break;
case2:
P2=bit_ser[2];
if(setflag==2)
P0=flag|seven_seg[dis_buffer[2]];
P0=seven_seg[dis_buffer[2]];
break;
case3:
P2=bit_ser[3];
if(setflag==2)
P0=flag|seven_seg[dis_buffer[3]];
P0=seven_seg[dis_buffer[3]];
break;
case4:
P2=bit_ser[4];
if(setflag==1)
P0=flag|seven_seg[dis_buffer[4]];
P0=seven_seg[dis_buffer[4]];
break;
case5:
P2=bit_ser[5];
if(setflag==1)
P0=flag|seven_seg[dis_buffer[5]];
P0=seven_seg[dis_buffer[5]];
break;
if(i>=6)
if(j==10)
if(setflag==0)
DS1302_GetTime(&Time);//如果setflag是0,就从1302中读出时间,因为setflag不是0时,说明处于调整状态,不需要读时间
dis_buffer[5]=Time.Second%10;//把当前时间放入显示缓冲区
dis_buffer[4]=Time.Second/10;
dis_buffer[3]=Time.Minute%10;
dis_buffer[2]=Time.Minute/10;
dis_buffer[1]=Time.Hour%10;
dis_buffer[0]=Time.Hour/10;
voidmain()
Initial_DS1302(Time);
timer0_init();
while(1)
set_down();
timer_down();
up_down();
down_down();
beepflag_down();
if(setflag==0&&Time.Hour==romhour&&Time.Minute==romminute&&Beepflag==1)//判断蜂鸣器是否要响
Beep=!Beep;
//key.c
#include
#defineucharunsignedchar
#defineuintunsignedint
uchari=0,j=0,x=0,setflag,flag_set,flag_timer;//setflag用来表示调整的位置,flag_set和flag_timer分别表示当前处于调整状态还是定时状态
SYSTEMTIMETime={0,20,15,3,30,6,10};//系统时间的初始值2010年6月30日星期三,15时20分0秒
chardis_buffer[6];//存放显示数据的缓冲区
sbitBeep_flag=P3^2;//蜂鸣器的接口
sbitkey_timer=P3^4;//定时按钮
sbitkey_set=P3^5;//调整按钮
sbitkey_up=P3^6;//增加按钮
sbitkey_down=P3^7;//减小按钮
charromhour,romminute,romsec;//分别存放定时的时,分,秒
bitBeepflag;//标记闹钟是否开启
//延时函数
voiddelays(ucharx)
while(x)x--;
//设置键的处理函数
voidset()
setflag++;
flag_set=1;
if(setflag>=4)
setflag=0;
flag_set=0;
Initial_DS1302(Time);
//定时间的处理函数
voidtimer()
setflag++;
flag_timer=1;
if(setflag==1)
Time.Hour=romhour;
Time.Minute=romminute;
Time.Second=romsec;
elseif(setflag>=4)
setflag=0;
flag_timer=0;
romhour=Time.Hour;
romminute=Time.Minute;
romsec=Time.Second;
//增加键的处理函数
voidup()
switch(setflag)
case0:
break;
case1:
Time.Second++;
if(Time.Second>=60)
Time.Second=0;
break;
case2:
Time.Minute++;
if(Time.Minute>=60)
Time.Minute=0;
break;
case3:
Time.Hour++;
if(Time.Hour>=24)
Time.Hour=0;
break;
//减小键的处理函数
voiddown()
switch(setflag)
case0:
break;
case1:
Time.Second--;
if(Time.Second<0)
Time.Second=59;
break;
case2:
Time.Minute--;
if(Time.Minute<0)
Time.Minute=59;
break;
case3:
Time.Hour--;
if(Time.Hour<0)
Time.Hour=23;
break;
//设置键的扫描函数
voidset_down()
if(key_set==0&&flag_timer==0)
delays(100);
if(key_set==0)
set();
while(!key_set);
//定时键的扫描函数
voidtimer_down()
if(key_timer==0&&flag_set==0)
delays(100);
if(key_timer==0)
timer();
while(!key_timer);
//增加键的扫描函数
voidup_down()
if(key_up==0&&setflag!=0)
delays(100);
if(key_up==0)
up();
while(!key_up);
//减少键的处理函数
voiddown_down()
if(key_down==0&&setflag!=0)
delays(100);
if(key_down==0)
down();
while(!key_down);
//定时开关的扫描处理函数
voidbeepflag_down()
if(Beep_flag==0)
delays(100);
Beepflag=!Beepflag;
while(!Beep_flag);
//ds1302.h
#ifndef_REAL_TIMER_DS1302
#define_REAL_TIMER_DS1302
#include
sbitDS1302_CLK=P1^1;//实时时钟时钟线引脚
sbitDS1302_IO=P1^2;//实时时钟数据线引脚
sbitDS1302_RST=P1^3;//实时时钟复位线引脚
sbitACC0=ACC^0;
sbitACC7=ACC^7;
sbitBeep=P2^7;
typedefstruct__SYSTEMTIME__
{charSecond;
charMinute;
charHour;
charWeek;
charDay;
charMonth;
charYear;
}SYSTEMTIME;//定义的时间类型
#defineAM(X)X
#definePM(X)(X+12)//转成24小时制
#defineDS1302_SECOND0x80//秒寄存器
#defineDS1302_MINUTE0x82//分寄存器
#defineDS1302_HOUR0x84
#defineDS1302_WEEK0x8A
#defineDS1302_DAY0x86
#defineDS1302_MONTH0x88
#defineDS1302_YEAR0x8C
#defineDS1302_RAM(X)(0xC0+(X)*2)//用于计算DS1302_RAM地址的宏
voidDS1302InputByte(unsignedchard)//实时时钟写入一字节(内部函数)
{unsignedchari;
ACC=d;
for(i=8;i>0;i--)
{DS1302_IO=ACC0;//相当于汇编中的RRC
DS1302_CLK=1;
DS1302_CLK=0;//发一个高跳变到低的脉冲
ACC=ACC>>1;
unsignedcharDS1302OutputByte(void)//实时时钟读取一字节(内部函数)
{unsignedchari;
for(i=8;i>0;i--)
{ACC=ACC>>1;//相当于汇编中的RRC
ACC7=DS1302_IO;
DS1302_CLK=1;
DS1302_CLK=0;//发一个高跳变到低的脉冲
return(ACC);
voidWrite1302(unsignedcharucAddr,unsignedcharucDa)//ucAddr:DS1302地址,ucData:要写的数据
{DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr);//地址,命令
DS1302InputByte(ucDa);//写1Byte数据
DS1302_CLK=1;
DS1302_RST=0;//RST0->1->0,CLK0->1
unsignedcharRead1302(unsignedcharucAddr)//读取DS1302某地址的数据
{unsignedcharucData;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;//enable
DS1302InputByte(ucAddr|0x01);//地址,命令
ucData=DS1302OutputByte();//读1Byte数据
DS1302_CLK=1;//RST0->1->0,CLK0->1
DS1302_RST=0;
return(ucData);
voidDS1302_SetProtect(bitflag)//是否写保护
{if(flag)
Write1302(0x8E,0x80);//WP=1,不能写入
Write1302(0x8E,0x00);//WP=0,可以写入
voidDS1302_SetTime(unsignedcharAddress,unsignedcharValue)//设置时间函数
{DS1302_SetProtect(0);
Write1302(Address,((Value/10)<<4|(Value%10)));//高4位为十位,低4位为个位
DS1302_SetProtect(1);
//获取时间函数,从DS1302内读取时间然后存入Time内
voidDS1302_GetTime(SYSTEMTIME*Time)
{unsignedcharReadValue;
ReadValue=Read1302(DS1302_SECOND);
Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//转换成10进制的秒
ReadValue=Read1302(DS1302_MINUTE);
Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_HOUR);
Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_DAY);
Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_WEEK);
Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_MONTH);
Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_YEAR);
Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
//利用STime初始化DS1302
voidInitial_DS1302(SYSTEMTIMESTime)
{unsignedcharSecond=Read1302(DS1302_SECOND);
if(Second&0x80)DS1302_SetTime(DS1302_SECOND,0);//如果第七为1(表明没有启动),则启动时钟
DS1302_SetTime(DS1302_SECOND,STime.Second);//设定起始时间
DS1302_SetTime(DS1302_MINUTE,STime.Minute);
DS1302_SetTime(DS1302_HOUR,STime.Hour);
DS1302_SetTime(DS1302_DAY,STime.Day);
DS1302_SetTime(DS1302_MONTH,STime.Month);
DS1302_SetTime(DS1302_YEAR,STime.Year);
DS1302_SetTime(DS1302_WEEK,STime.Week);
#endif
本回答由网友推荐