单片机例程.docx
《单片机例程.docx》由会员分享,可在线阅读,更多相关《单片机例程.docx(14页珍藏版)》请在冰豆网上搜索。
![单片机例程.docx](https://file1.bdocx.com/fileroot1/2022-11/23/2ae484d3-341c-42d3-a7b2-ce814c96039b/2ae484d3-341c-42d3-a7b2-ce814c96039b1.gif)
单片机例程
试验数码管上显示数字
(单片机直接实现位选共阴极)*
连接方法:
P0与J12用8PIN排线连接P1与JP16用排线连接请学员认真消化本例程,用573锁存器控制和单片机脚直接位选控制(非译码器控制)数码管
#include
#include
voiddelay(unsignedinti);//函数声名
charDelayCNT;//定义变量
//此表为LED的字模,共阴数码管0-9-
unsignedcharcodeDisp_Tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//段码控制
//此表为8个数码管位选控制,共阴数码管1-8个-
unsignedcharcodedispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F};//位选控制查表的方法控制
/************主函数**********************/
main()
{
unsignedinti,LedNumVal=1;//变量定义
unsignedintLedOut[10];//变量定义
DelayCNT=0;
while
(1)
{
if(++DelayCNT>=20)//控制数字变化速度
{DelayCNT=0;//20个扫描周期清零一次
++LedNumVal;//每隔20个扫描周期加一次}
LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
LedOut[1]=Disp_Tab[LedNumVal%1000/100]|0x80;
LedOut[2]=Disp_Tab[LedNumVal%100/10];
LedOut[3]=Disp_Tab[LedNumVal%10];
LedOut[4]=Disp_Tab[LedNumVal%10000/1000];//千位
LedOut[5]=Disp_Tab[LedNumVal%1000/100]|0x80;//百位带小数点
LedOut[6]=Disp_Tab[LedNumVal%100/10];//十位
LedOut[7]=Disp_Tab[LedNumVal%10];//个位
for(i=0;i<9;i++)
{P0=LedOut[i];
P1=dispbit[i];//使用查表法进行位选
/*switch(i)//使用switch语句控制位选
{
case0:
P1=0x7F;break;
case1:
P1=0xbF;break;
case2:
P1=0xdF;break;
case3:
P1=0xeF;break;
case4:
P1=0xf7;break;
case5:
P1=0xfb;break;
case6:
P1=0xfd;break;
case7:
P1=0xfe;break;
}*/
delay(150);//扫描间隔时间太长会数码管会有闪烁感
}
}
}
voiddelay(unsignedinti)
{charj;
for(i;i>0;i--)
for(j=200;j>0;j--);
}
试验数码管上显示数字
(译码器位选共阴极)*
*连接方法:
P0与J12用8PIN排线连接
*请学员认真消化本例程,用573锁存器和译码器控制和数码管#include
#include
sbitLS138A=P2^2;//定义138译码器的输入A脚由P2.2控制
sbitLS138B=P2^3;//定义138译码器的输入脚B由P2.3控制
sbitLS138C=P2^4;//定义138译码器的输入脚C由P2.4控制
voiddelay(unsignedinti);//函数声名
charDelayCNT;//此表为LED的字模,共阴数码管0-9-
unsignedcharcodeDisp_Tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
/************主函数**********************/
main()
{
unsignedinti,LedNumVal=1;
unsignedintLedOut[10];
DelayCNT=0;
while
(1)//进入循环状态
{
if(++DelayCNT>=50)
{
DelayCNT=0;//延时计数每扫描一次加一次
++LedNumVal;//每隔50个扫描周期加一次
}
LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
LedOut[1]=Disp_Tab[LedNumVal%1000/100]|0x80;
LedOut[2]=Disp_Tab[LedNumVal%100/10];
LedOut[3]=Disp_Tab[LedNumVal%10];
LedOut[4]=Disp_Tab[LedNumVal%10000/1000];//千位
LedOut[5]=Disp_Tab[LedNumVal%1000/100]|0x80;//百位带小数点
LedOut[6]=Disp_Tab[LedNumVal%100/10];//十位
LedOut[7]=Disp_Tab[LedNumVal%10];//个位
for(i=0;i<9;i++)//实现8位动态扫描循环
{
P0=LedOut[i];//将字模送到P0口显示
switch(i)//使用switch语句控制位选也可以是用查表的方式学员可以试着自己修改
{
case0:
LS138A=0;LS138B=0;LS138C=0;break;
case1:
LS138A=1;LS138B=0;LS138C=0;break;
case2:
LS138A=0;LS138B=1;LS138C=0;break;
case3:
LS138A=1;LS138B=1;LS138C=0;break;
case4:
LS138A=0;LS138B=0;LS138C=1;break;
case5:
LS138A=1;LS138B=0;LS138C=1;break;
case6:
LS138A=0;LS138B=1;LS138C=1;break;
case7:
LS138A=1;LS138B=1;LS138C=1;break;
}
delay(150);
}
}
}
*voiddelay(unsignedinti)
{
charj;
for(i;i>0;i--)
for(j=200;j>0;j--);
}
1位数码管上显示外部中断计数
*连接方法:
P0与JP3P3与JP5用8PIN排线连接P3.2外部中断输入*
*请学员认真消化本例程,用单片机脚直接控制数码管和外部中断使用
#include
#include
unsignedintLedNumVal;
unsignedcharcodeDisp_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0xbf,0xc7,0x8c,0xc1,0xff,0xf7};
/********************************************************
*主程序*
********************************************************/
voidmain(void)
{
//IT0=0;//低电平触发
IT0=1;//下降沿触发
EA=1;
EX0=1;
while
(1)
{
P0=Disp_Tab[LedNumVal%10];
}
}
/********************************************************
*INT0中断函数*
********************************************************/
voidcounter(void)interrupt0
{
EX0=0;
LedNumVal++;//中断计数
EX0=1;
}
试验4位数码管上显示外部中断计数
*连接方法:
P0与J12P3与JP5用8PIN排线连接P3.2外部中断输入JP15和JP16用8个短路冒连上
*请学员认真消化本例程,用单片机通过译码器控制数码管和外部中断使用*
#include
#include
sbitLS138A=P2^2;
sbitLS138B=P2^3;
sbitLS138C=P2^4;
unsignedintLedNumVal=0,LedOut[8];
unsignedcharcodeDisp_Tab[]={~0xC0,~0xF9,~0xA4,~0xB0,~0x99,~0x92,~0x82,~0xF8,~0x80,~0x90,~0x88,~0x83,~0xC6,~0xA1,~0x86,~0xbf,~0xc7,~0x8c,~0xc1,~0xff,~0xf7};
voiddelay(unsignedinti)
{charj;
for(i;i>0;i--)
for(j=200;j>0;j--);}
display()
{unsignedchari;
LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
LedOut[1]=Disp_Tab[LedNumVal%1000/100]&0x7f;
LedOut[2]=Disp_Tab[LedNumVal%100/10];
LedOut[3]=Disp_Tab[LedNumVal%10];
for(i=0;i<8;i++)
{P0=LedOut[i];
switch(i)
{case0:
LS138A=0;LS138B=0;LS138C=0;break;
case1:
LS138A=1;LS138B=0;LS138C=0;break;
case2:
LS138A=0;LS138B=1;LS138C=0;break;
case3:
LS138A=1;LS138B=1;LS138C=0;break;
case4:
LS138A=0;LS138B=0;LS138C=1;break;
case5:
LS138A=1;LS138B=0;LS138C=1;break;
case6:
LS138A=0;LS138B=1;LS138C=1;break;
case7:
LS138A=1;LS138B=1;LS138C=1;break;
}
delay(150);
}}
/********************************************************
*主程序*
********************************************************/
voidmain(void)
{P0=0xff;
P1=0xff;
P2=0xff;
//IT0=0;//低电平触发
IT0=1;//下降沿触发
EA=1;
EX0=1;
while
(1)
{
display();
}
}
/********************************************************
*INT0中断函数*
********************************************************/
voidcounter(void)interrupt0
{
//unsignedcharx;
EX0=0;
LedNumVal++;//中断计数
EX0=1;
}
试验数码管显示时钟
*通过本例程了解DS1302时钟芯片的基本原理和使用,理解并掌握DS1302时钟芯片驱动程序的编写以及实现数字字符在数码管中的显示。
注意:
JP1302跳线冒要短接。
请学员认真消化本例程,懂DS1302在C语言中的操作
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include
sbitSCK=P3^6;//时钟
sbitSDA=P3^4;//数据
sbitRST=P3^5;//DS1302复位
sbitLS138A=P2^2;
sbitLS138B=P2^3;
sbitLS138C=P2^4;
bitReadRTC_Flag;//定义读DS1302标志
unsignedcharl_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-1512:
00:
00
unsignedcharl_tmpdisplay[8];
codeunsignedcharwrite_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//秒分时日月周年最低位读写位
codeunsignedcharread_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
codeunsignedchartable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管0-9'-''熄灭‘表
/******************************************************************/
/*函数声明*/
/******************************************************************/voidWrite_Ds1302_byte(unsignedchartemp);
voidWrite_Ds1302(unsignedcharaddress,unsignedchardat);
unsignedcharRead_Ds1302(unsignedcharaddress);
voidRead_RTC(void);//readRTC
voidSet_RTC(void);//setRTC
voidInitTIMER0(void);//initaltimer0
/******************************************************************/
/*主函数*/
/******************************************************************/
voidmain(void)
{InitTIMER0();//初始化定时器0
Set_RTC();//写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
while
(1)
{if(ReadRTC_Flag)
{ReadRTC_Flag=0;
Read_RTC();
l_tmpdisplay[0]=l_tmpdate[2]/16;//数据的转换,因我们采用数码管0~9的显示,将数据分开
l_tmpdisplay[1]=l_tmpdate[2]&0x0f;
l_tmpdisplay[2]=10;//加入"-"
l_tmpdisplay[3]=l_tmpdate[1]/16;
l_tmpdisplay[4]=l_tmpdate[1]&0x0f;
l_tmpdisplay[5]=10;
l_tmpdisplay[6]=l_tmpdate[0]/16;
l_tmpdisplay[7]=l_tmpdate[0]&0x0f;
}}}
/******************************************************************/
/*定时器0初始化*/
/******************************************************************/
voidInitTIMER0(void)
{TMOD|=0x01;//定时器设置16位
TH0=0xef;//初始化值
TL0=0xf0;
ET0=1;
TR0=1;
EA=1;}
/******************************************************************/
/*写一个字节*/
/******************************************************************/
voidWrite_Ds1302_Byte(unsignedchartemp)
{
unsignedchari;
for(i=0;i<8;i++)//循环8次写入数据
{
SCK=0;
SDA=temp&0x01;//每次传输低字节
temp>>=1;//右移一位
SCK=1;
}}
/******************************************************************/
/*写入DS1302*/
/******************************************************************/
voidWrite_Ds1302(unsignedcharaddress,unsignedchardat)
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();//启动
Write_Ds1302_Byte(address);//发送地址
Write_Ds1302_Byte(dat);//发送数据
RST=0;//恢复
}
/******************************************************************/
/*读出DS1302数据*/
/******************************************************************/
unsignedcharRead_Ds1302(unsignedcharaddress)
{unsignedchari,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for(i=0;i<8;i++)//循环8次读取数据
{if(SDA)
temp|=0x80;//每次传输低字节
SCK=0;
temp>>=1;//右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_();//以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return(temp);//返回
}
/******************************************************************/
/*读时钟数据*/
/******************************************************************/
voidRead_RTC(void)//读取日历
{
unsignedchari,*p;
p=read_rtc_address;//地址传递
for(i=0;i<7;i++)//分7次读取秒分时日月周年
{
l_tmpdate[i]=Read_Ds1302(*p);
p++;
}}
/******************************************************************/
/*设定时钟数据*/
/******************************************************************/
voidSet_RTC(void)//设定日历
{
unsignedchari,*p,tmp;
for(i=0;i<7;i++){//BCD处理
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0X00);
p=write