立刻大四了,行将找作业。所以便把我学过的东西总结一下,体系一下。
接下来,就把我总结的成果跟我们共享下。
这一章是51单片机,主要是程序实例。代码参阅郭天祥的单片机教材。
是总括性的,适合于有必定单片机根底的同学,也能够给初学者做一个体系的学习主线。
这个博客里的触及的源代码我们能够在这儿下载http://download.csdn.net/detail/zhaole20094463/4427745
1.流水灯
/流水灯/
#include
#include
#define uint unsigned int //宏界说 界说uint 在大项目中愈加的便利
#define uchar unsigned char
void delayms(uint);
uchar aa;
void main()
{
aa=0xfe;
while(1)
{
P1=aa;
delayms(500);
aa=_crol_(aa,1);//aa左移一位
}
}
void delayms(uint xms)//延时时刻约为1ms经过程序单步碑文,看运转时刻可得到
{
uint i,j;
for(i=xms;i>0;i–)
for(j=110;j>0;j–);
}
经过调用体系函数的方法使流水灯完成循环左移。
2.数码管显现程序
/*锁存器用的是74HC573高电平通,低电平锁存*/
/*效果:高阻态 ,数据锁存 ,数据缓冲 (加强驱动才能)*/
/*循环显现1-A的数据*/
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
uchar num;
uchar code table[]={数码管段码表};
void main()
{
wela=1;//翻开锁存器
P0=0xc0;//送入锁存信号
wela=0;//封闭锁存器
while(1)
{
for(num=0;num<16;num++)
dula=1;
P0=table[num];
delayms(500);
}
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i–)
for(j=110;j>0;j–);
}
3.独立键盘检测
/*经过按键操控led亮灭*/
#include
#define uint unsigned int
#define uchar unsigned char
sbit key1=P3^4;
sbit led=P1^0;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x–)
for(y=110;y>0;y–);
}
void main()
{
P3=0xff;//在对51单片机进行按键检测时,先要将引脚置1;
while(1)
{
if(key1==0)
{
delay(5);
if(key1==0)//按键消抖
{
led=0;
num++;
if(num==2)
num=0;
led=1;
}
}
4.矩阵键盘检测
/*检测矩阵键盘数码管显现0-F/
矩阵键盘的四列与P3.4~P3.7相连
4行与P3.0~P3.3
#include
#define uchar unsinged char
#define uint unsigned int
sbit dula=P2^6;
sbint wela=P2^7;
uchar code table[]={段码表};
void delayms(uint xms);
{
uint i,j;
for(i=xms;i>0;i–)
for(j=110;j>0;j–);
}
void display(uchar num)显现函数
{
P0=table[num];
dula=1;
dula=0;
}
void matrixkeyscan()//矩阵键盘的检测
{
uchar temp,key;
P3=0xfe;//翻开P3.7,P3.7置0.检测高四位
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//是否有键被按下
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//按键消抖
{
temp=P3;
switch(temp)
{
case 0xee:key=0;break;
case 0xde:key=1;break;
case 0xbe:key=2;break
case 0x7e:key=3:break;
}
while(temp!=0xf0)//检测按键是否弹起,假如没有弹起循环停在这儿。
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
。。。。。。。。。。。。。。。。。。。
如下程序顺次添加
令P3=0xfd,翻开P3.6,P3.6置低,检测高四位 顺次为 4,5,6,7
然后令P3= 0xfb 0xf7
}
void main()
{
P0=0;//封闭一切数码管的段选
dula=1;
dula=0;
P0=0xc0;
wela=1;
wela=0;
while(1)
{
matrixkeyscan();//不断调用键盘扫描程序
此程序关键在于这个函数,矩阵键盘的扫描算法
}
}
5.1602液晶屏显现子函数
//
这个程序主要是有这样几个子函数,关于lcd写指令和写数据的
#include
#define uchar unsigned char
#define uint unsigned int
uchar code table[]=”zhaole20094463″;
uchar code table1[]=”love Embedded systems”;
sbit lcden=P3^4;//lcd使能端
sbit lcdrs=P3^5;//lcd数据指令挑选端
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x–)
for(y=110;y>0;y–);
}
void write_com(uchar com)//lcd写指令函数
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lceen=0;
}
void write_data(uchar date)//lcd写数据
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);//设置16*2显现,5*7点阵,8位数据接口
write_com(0x0c);//设置开显现,不显现光标
write_com(0x06);//写榜首个字符后地址指针加1
write_com(0x01);//显现清0,数据指针清0
}
void main()
{
init();
write_com(0x80);//数据指针定位在榜首行的榜首个字处
for(num=0;num<14;num++)
{
write_data(table[num]);
delay(5);
}
write_com(0x80+0x40);//数据指针定位在第二行的榜首个字处
for(num=0;num<21;num++)
{
write_data(table1[num]);
delay(5);
}
while(1);
}
5.2 12864显现子函数
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define LCD_data P0;//数据口
sbit LCD_RS=P3^5; //数据挑选输入
sbit LCD_RW=P3^6; //液晶读写操控
sbit LCD_EN=P3^4; //液晶使能操控端
sbit LCD_PSB=P3^7; //串并方法操控
void delay_1ms(uint )
{
uint i,j;
for(j=0j
}
/*PS=L,RW=L,E=高脉冲,D0~D7=指令码*/
void write_cmd(uchar cmd)
{
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
P0=cmd;
delay_1ms(5);
LCD_EN=0;
}
/*写显现数据到LCD*/
/*RS=H,RW=L,E=高脉冲,D0~D7=数据
void write_dat(uchar dat)
{
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=dat;
delay_1ms(5);
LCD_EN=1;
dealy_1ms(5);
LCD_EN=0;
}
/*设定显现方位*/
void LCD_pos(uchar X,uchar Y)
{
uchar pos;
if(X==0)
{X=0x80;}
else if(X==1);
{X=0x90;}
else if(x==2)
{X=0x88;}
else if(X==3)
{X=0x98;}
pos=X+Y;
write_cmd(pos);//显现地址
}
/*LCD初始化设置*/
void lcd_init()
{
LCD_PSB=1; //并口方法
write_cmd(0x30);//根本指令操作
delay_1ms(5);
write_cmd(0x0C);//先是开,关光标
delay_1ms(5);
write_cmd(0x01);//铲除LCD的显现内容
delay_1ms(5);
}
6.守时器中止
/*用守时器0的方法1完成榜首个发光管以1s亮灭*/
守时器/计数器4种作业方法
1,方法0 13位计数器 高8位和低5位
2,方法1 16位计数器
3,方法2 主动康复初值 8位
4,方法3 只适用于T0,不适用于T1 8位
45872初值的核算
晶振:11.0592M
机器周期:计数一次的时刻=12*(1/11.0592M)51单片机是12个时钟周期为一个机器周期
=1.09US 指令周期由整数个机器周期组成
45872 =50Ms/1.09us
//
#include
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar num;
void main()
{
TMOD=0x01;//设置守时器0作业方法1
TH0=(65535-45872)/256;//装初值11.0592M晶振守时50ms为45872
TL0=(65535-45872)%256;
EA=1; //开总中止
ET0=1; //开守时器0中止
TR0=1; //发动守时器0
while(1) //程序停在这儿等候中止的发生
}
void T0_time() interrupt 1
{
TH0=(65535-45872)/256;
TL0=(65535-45872)%256;
num++;
if(num==20)
{
num=0;
led1=~led1;
}
}
7.串口通讯
//
上位机经过串口调试帮手发送一个字符x,单片机收到字符后回来给上位机“I get x”
串口波特率设置为9600bps。
#include
#define uchar unsigned char
#define uint unsigned int
uchar flag,a,i;
uchar code table[]=”I get”;
void init()
{
TMOD=0x20;//设置T1守时器作业方法为2 8位初值主动重装的8位守时器
TH1=0xfd;//T1守时器装初值(高八位) 操控串口通讯的波特率(由守时器1的溢出率操控)
TL1=0xfd;///T1守时器装入初值(低八位)
TR1=1; //守时器1运转操控位 置一发动守时器
REN=1; //答应串口接纳
SM0=0;
SM1=1; //设置串口作业方法为一
EA=1; //大局中止答应位 置一开大局中止
ES=1; //串口中止答应位
}
void main()
{
init();
` while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI)
TI=0;//发送中止标志 发送数据完成后触发中止 硬件置一 有必要软件清零
}
SBUF=a;// 串口发送数据
while(!TI);
TI=0;
ES=1;
flag=0;
}
}
void ser() interrupt 4 //串口中止服务程序
{
RI=0; // 收到数据硬件置一,由软件清零
a=SBUF; //将寄存器的值 赋给a
flag=1; //标志位
}
留意:51单片机的特别之处在于,SBUF既是串口接纳寄存器也是串口发送寄存器,取决于
SBUF地点赋值符号“=”左右的方位
此程序中共用的串口中止,
守时器1中止 特别功用寄存器SBUF
中止呼应的条件
中止源有中止请求 此中止源答应位为1 cpu开中止(即EA=1)以上三个条件一起分量
串口通讯设置
确认串口通讯波特率(编程TMOD寄存器守时器作业方法寄存器)
核算守时器初值转载THX TLX
确认串行口作业方法(编程SCON寄存器串行口操控方法寄存器)
串行口作业在中止方法时,要进行中止设置如TI,RI软件清零
8.I2C总线通讯模仿子函数
/*/
由于51单片机没有I2C总线,所以选用模仿I2C通讯
1,总线初始化
void init()
{
SCL=1;
delay();
SDA=1;
delay();
}
2,发动信号
void start()
{
SDA=1;
delay(1);
SCL=1;
delay();
SDA=0;
delay();
}
3,应对信号
void respons()
{
uchar i=0;
SCL=1;
delay();
while((SDA==1)&&(i<255))
i++;
SCL=0;
delay();
}
4,中止信号
void stop()
{
SDA=0;
delay();
SCL=1;
delay();
SDA=1;
delay();
}
5,写一个字节
void writebyte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;
delay();
}
SCL=0;
delay();
SDA=1;
delay();
}
6,读一个字节
uchar readbyte()
{
uchar i,k;
SCL=0;
delay();
SDA=1;
for(i=0;i<8;i++)
{
SCL=1;
delay();
k=(k<<1)|SDA;
SCL=0;
delay();
}
delay();
return k;
}
9.看门狗
//
关于51单片机中的看门狗寄存器
D5 EN_WDT 看门狗答应位
D4 CLK_WDT 看门狗清零
D3 IDLE_WDT 看门狗IDLE形式位
PS0 PS1 PS2 看门狗守时器预分频值
这三个寄存器置不同的值决议不同的看门狗溢出时刻
看门狗溢出时刻=(N*预分频数*32768)/晶振频率
#include
#define uchar unsigned char
#define uint unsigned int
sfr WDT_CONTR=0xe1;//界说看门狗寄存器 reg52.h中没有对它进行界说
sbit led1=P1^0;
void delayms(uint xms)
{
uint i,j;
for(i=xms;j>0;j–)
for(j=110;j>0;j–);
}
void main()
{
WDT_CONTR=0x35;//0x35=0011 0101设置预分频数为 64 溢出时刻为2.0971s
led1=0;
delayms(500);
led1=1;
while(1)
{
delayms(1000);
WDT_CONTR=0x35;//喂狗查办将D4不断置1,一旦D4被清零则看门狗复位
}
}
10.软件完成体系复位
STC ISP/IAP操控寄存器(ISP_CONTR)
D7 ISPEN 功用答应位 0制止编程改动flash 1答应
D6 SWBS 0软件挑选从用户使用程序区发动 1从ISP程序区发动
D5 SWRST 不操作 1发生体系软件复位,硬件主动清零
D2 WT2
D1 WT1
D0 WT0 编程设定CPU等候的最长时刻,对flash进行读操作,写操作,擦除操作有必要在这个时刻内
SWBS=0 SWRST=1(软复位) 从用户使用程序区(AP区)软件复位并切换到用户使用程序区开端碑文程序
从哪里复位取决于程序在哪里碑文
SWBS=1 SWRST=1 从ISP监控程序区软件复位并切换ISP监控程序区开端碑文程序
使用方法:
进行软件复位时
首要
sfr ISP_CONTR=0xe7;界说ISP/IAP操控寄存器
然后再需求软件复位的当地参加如下查办即可
ISP_CONTR=0x20//用软件复位到用户使用程序区(AP),重新开端碑文程序
11.DS18B20编程使用子函数
//
Ds18B20的编程子函数
DS18B20是单总线接口的温度传感器,使用规模很广泛
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit ds=P2^2;//温度传感器信号线
uint temp;//界说整型的温度数据
float temp;//界说浮点型的温度数据
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x–)
for(y=110;y>0;y–);
}
void dsreset(void)//DS18B20复位,初始化函数
{
uint i;
ds=0;
i=103;
while(i>0)i–;
ds=1;
i=4;
while(i>0)i–;
}
bit tempreadbit(void)//读1位数据函数
{
uint i;
bit dat;
ds=0;i++;//i++起延时效果
ds=1;i++;i++;
dat=ds;
i=8;while(i>0)i–;
return(dat);
}
uchar tempread(void)//读1个字节数据函数
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样刚好一个字节在dat里
}
return(dat);
}
void tempwritebyte(uchar dat)//向DS18B20写一个字节数据函数
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb)//写1
{
ds=0;
i++;i++;
ds=1;
i=8;while(i>0)i–;
}
else//写0
{
ds=0;
i=8;while(i>0)i–;
ds=1;
i++;i++;
}
}
}
void tempchange(void)//DS18B20 开端获取温度并转化
{
dsreset();
delay(1);
tempwritebyte(0xcc);//写 越过读ROM指令
tempwritebyte(0x44);//写 温度转化指令
}
uint get_temp()
{
uchar a,b;
dsreset();
delay(1);
tempwritebyte(0xcc);
tempwritebyte(0xbe);//读内部ram中的9字节
a=tempread();//读低8位
b=tempreda();//读高8位
temp=b;
temp<<=8;
temp=temp | a;//两个字节组合为1个字
f_temp = temp*0.0625;//温度在寄存器中为12位,分辨率为0.0625 厂家出厂时默许精度为12位,所以乘以0.0625
temp=f_temp*10+0.5; //乘以10一共小数点后边只取一位,加0.5是为了四舍五入
f_temp=f_temp+0.05;
return temp;
}
12.内部ram的扩展
51单片机存储器形式一共有三种
small形式 默许变量存储在单片机内部的128B RAM中
无声明均以这个形式存储
compact形式 默许变量存储在单片机内部的 256B RAM中
关键字 pdata :unsinged char pdata a[100]
large 形式 默许变量均存储在64K的RAM区包含内部ram和外部ram
关键字 xdata:unsingned char xdata a[100]
三种形式的不同:拜访速度由快到慢
这个博客里的触及的源代码我们能够在这儿下载http://download.csdn.net/detail/zhaole20094463/4427745