单片机课程笔记Word文件下载.docx
- 文档编号:16289169
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:54
- 大小:97.34KB
单片机课程笔记Word文件下载.docx
《单片机课程笔记Word文件下载.docx》由会员分享,可在线阅读,更多相关《单片机课程笔记Word文件下载.docx(54页珍藏版)》请在冰豆网上搜索。
6、While
(1);
表示无限执行该语句,即死循环。
语句后的分号表示空循环体,也就是{;
}
第一章单片机最小应用系统:
单片机最小系统的硬件原理接线图:
1、接电源:
VCC(PIN40)、GND(PIN20)。
加接退耦电容0.1uF
2、接晶体:
X1(PIN18)、X2(PIN19)。
注意标出晶体频率(选用12MHz),还有辅助电容30pF
3、接复位:
RES(PIN9)。
接上电复位电路,以及手动复位电路,分析复位工作原理
4、接配置:
EA(PIN31)。
说明原因。
具体接法如下图所示:
第二章基本I/O口的应用。
例1:
用P1口输出一倍频方波。
#include<
reg52.h>
//reg52.h为包含51资源的库文件
voidmain(void)
{
while(1==1)
{
++P1;
//使P1口加一完成一倍频方波,
}
P0的每个引脚要输出高电平时,必须外接上拉电阻(如4K7)至VCC电源。
例2:
用P1口输出一倍频方波,要求能用万用表测出方波。
其实,只需要在上面的程序中添加延时程序即可。
unsignedinti,j;
while(1==1)
for(i=0;
i<
1000;
i++)
for(j=0;
j<
j++);
//该循环是一个大概的延时,具体时间要看汇编语言的指令才能判断。
例3:
要求从P1口输出一方波,要求P1.7变化的最快,P1.0变化的最慢。
unsignedcharm,n;
//定义两个中间变量完成交换过程
while
(1)
n=0;
++m;
n|=(m<
<
7)&
0x80;
//将第0位的值送至第7位
5)&
0x40;
//将第1位的值送至第6位
3)&
0x20;
//将第2位的值送至第5位
1)&
0x10;
//将第3位的值送至第4位
n|=(m>
>
0x08;
//将第4位的值送至第3位
0x04;
//将第5位的值送至第2位
0x02;
//将第6位的值送至第1位
0x01;
//将第7位的值送至第0位
P1=n;
for(i=0;
i++)
for(j=0;
一个字节的8位D7、D6至D0,分别输出到P3.7、P3.6至P3.0,比如P3=0x0f,则P3.7、P3.6、P3.5、P3.4四个引脚都输出低电平,而P3.3、P3.2、P3.1、P3.0四个引脚都输出高电平。
同样,输入一个端口P2,即是将P2.7、P2.6至P2.0,读入到一个字节的8位D7、D6至D0。
第三章显示驱动
数码管的接法和驱动原理
一支七段数码管实际由8个发光二极管构成,其中7个组形构成数字8的七段笔画,所以称为七段数码管,而余下的1个发光二极管作为小数点。
作为习惯,分别给8个发光二极管标上记号:
a,b,c,d,e,f,g,h。
对应8的顶上一画,按顺时针方向排,中间一画为g,小数点为h。
我们通常又将各二极与一个字节的8位对应,a(D0),b(D1),c(D2),d(D3),e(D4),f(D5),g(D6),h(D7),相应8个发光二极管正好与单片机一个端口Pn的8个引脚连接,这样单片机就可以通过引脚输出高低电平控制8个发光二极的亮与灭,从而显示各种数字和符号;
对应字节,引脚接法为:
a(Pn.0),b(Pn.1),c(Pn.2),d(Pn.3),e(Pn.4),f(Pn.5),g(Pn.6),h(Pn.7)。
如果将8个发光二极管的负极(阴极)内接在一起,作为数码管的一个引脚,这种数码管则被称为共阴数码管,共同的引脚则称为共阴极,8个正极则为段极。
否则,如果是将正极(阳极)内接在一起引出的,则称为共阳数码管,共同的引脚则称为共阳极,8个负极则为段极。
以单支共阴数码管为例,可将段极接到某端口Pn,共阴极接GND,则可编写出对应十六进制码的七段码表字节数据如下图:
动态显示的电路连接如下图所示:
P1口
下面,我们编程在数码管上显示出“1234”。
程序如下:
CodeunsignedcharSeg7Code[16]=//用十六进数作为数组下标,可直接取得对应的七段编码字节
//0123456789AbCdEF
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsignedinti;
P2|=0x0f;
//消隐,让数码管开始处于不亮的状态
P0=LedCode[1];
//将“1”的代码送出
P2&
=0xfe;
//选中第一个数码管
for(i=0;
i++);
P2|=0x0f;
P0=LedCode[2];
=0xfd;
P0=LedCode[3];
=0xfb;
for(i=0;
P0=LedCode[4];
=0xf7;
关于DRIVER
编写DRIVER的目的是让程序能适应更多的场合,让我们的使用更加方便,大家可以把一些自己编过的有用的程序做成DRIVER便于自己以后的使用。
下面介绍显示的驱动程序:
首先,定义一个头文档<
LedDriver.H>
,描述可用函数,如下:
#ifndef_LedDriver_H_//防止重复引用该文档,如果没有定义过符号_KEY_H_,则编译下面语句
#define_LedDriver_H_//只要引用过一次,即#include<
key.h>
,则定义符号_KEY_H_
voidLedPrint(unsignedcharDat)//数据缓冲区间,完成移位功能
voidLedWork(void)//送数到显示数码管
#endif
然后,定义函数体文档LedDriver.C,如下:
#include“LedDriver.h”
CodeunsignedcharLedCode[16]=//Code是表示这个数组的存储空间
unsignedcharDisBuf[4];
voidLedPrint(unsignedcharDat)
DisBuf[0]=DisBuf[1];
//每次用后一个数冲掉前一个数,便于扩展显示位数
DisBuf[1]=DisBuf[2];
DisBuf[2]=DisBuf[3];
DisBuf[3]=Dat;
voidLedWork(void)
staticunsignedchari=0;
//static表示静态变量,指变量的赋值只在第一次定义的时候赋
P2|=0x0f;
P0=LedCode[DisBuf[i]];
Switch(i)//选择数据送到哪个管子
case0:
P2_0=0;
break;
case1:
P2_1=0;
case2:
P2_2=0;
case3:
P2_3=0;
if(++i>
=4)i=0;
//判断四位数是否都已经送完
for(m=0;
m<
m++);
//延时
这样DRIVER的程序就编好了,我们以后用的时候直接调用函数就可以了。
主程序可以编写如下:
voidmian(void)
LedPrint
(1);
//调用函数,把想显示的数据送如缓存
LedPrint
(2);
LedPrint(3);
LedPrint(4);
While
(1)
LedWork();
下面介绍一个例子供大家参考。
显示“12345678”
P1端口接8联共阴数码管SLED8的段极:
P1.7接段h,…,P1.0接段a
P2端口接8联共阴数码管SLED8的段极:
P2.7接左边的共阴极,…,P2.0接右边的共阴极
方案说明:
晶振频率fosc=12MHz,数码管采用动态刷新方式显示,在1ms定时断服务程序中实现
unsignedcharDisBuf[8];
//全局显示缓冲区,DisBuf[0]对应右SLED,DisBuf[7]对应左SLED,
voidDisplayBrush(void)
{codeunsignedcharcathode[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//阴极控制码
codeunsignedcharSeg7Code[16]=//用十六进数作为数组下标,可直接取得对应的七段编码字节
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
staticunsignedchari=0;
//(0≤i≤7)循环刷新显示,由于是静态变量,此赋值只做一次。
P2=0xff;
//显示消隐,以免下一段码值显示在前一支SLED
P1=Seg7Code[DisBuf[i]];
//从显示缓冲区取出原始数据,查表变为七段码后送出显示
P2=cathode[i];
//将对应阴极置低,显示
if(++i>
=8)i=0;
//指向下一个数码管和相应数据
voidTimer0IntRoute(void)interrupt1
TL0=-1000;
//由于TL0只有8bits,所以将(-1000)低8位赋给TL0
TH0=(-1000)>
8;
//取(-1000)的高8位赋给TH0,重新定时1ms
DisplayBrush();
voidTimer0Init(void)
{
TMOD=(TMOD&
0xf0)|0x01;
//初始化,定时器T0,工作方式1
TL0=-1000;
//定时1ms
TR0=1;
//允许T0开始计数
ET0=1;
//允许T0计数溢出时产生中断请求
voidDisplay(unsignedcharindex,unsignedchardataValue)
DisBuf[index]=dataValue;
voidmain(void)
unsignedchari;
for(i=0;
i<
i++){Display(i,8-i);
区qhkode[DisBuf[i]];
//;
f7,0xfd,0xfb,0xfe};
}//DisBuf[0]为右,DisBuf[0]为左
Timer0Init();
EA=1;
//允许CPU响应中断请求
While
(1);
第四章键盘驱动
单片机I/O口作为输入的前提是必须首先输出一个高电平。
charKbhit(void)
{
P1.0P1_0=1;
if(P1_9==0)return
(1);
elsereturn(0);
)
下面我们对上面的程序作个改进:
charKbhit(void)
P1=0xff;
if((P1^0xff)!
=0)return
(1);
一般来说,按键的时候会有抖动,我们可以用加延时的办法来去除抖动。
即:
P1=0xff;
if((P1^0xff)!
=0)
延时20ms;
if((P1^0xff)!
=0)return
(1);
4X4按键。
由P1端口的高4位和低4位构成4X4的矩阵键盘,本程序只认为单键操作为合法,同时按多键时无效。
取键值的程序如下:
unsignedchargetch(void)
unsignedcharX,Y,Z;
P1=0xf0;
X=P1;
P1=0x0f;
Y=P1;
Z=X|Y;
switch(Z)
case0xee:
return(0);
case0xde:
return
(1);
case0xbe:
return
(2);
case0x7e:
return(3);
case0xed:
return(4);
case0xdd:
return(5);
case0xbd:
return(6);
case0x7d:
return(7);
case0xeb:
return(8);
case0xdb:
return(9);
case0xbb:
return(10);
case0x7b:
return(11);
case0xe7:
return(12);
case0xd7:
return(13);
case0xb7:
return(14);
case0x77:
return(15);
判断有无键按下的程序:
P1=0xf0;
if(P1==0xf0)return(0);
elsereturn
(1);
下面是键盘的Driver程序:
首先我们还是来写KeyDriver.h这个程序:
#ifndef_KeyDriver_h_
#define_KeyDriver_h_
charKhbit(void);
charGetch(void);
接着,我们来写KeyDriver.c程序
#include“KeyDriver.h”
按键显示程序如下:
reg52.h>
unsignedchari;
for(i=1;
5;
{LedPrint(i);
while
(1)
if(Kbhit())
{LedPrint(Getch());
LedWork();
下面是另一个键盘值的算法,供大家参考。
定义一个头文档<
KEY.H>
#ifndef_KEY_H_//防止重复引用该文档,如果没有定义过符号_KEY_H_,则编译下面语句
#define_KEY_H_//只要引用过一次,即#include<
unsignedcharkeyHit(void);
//如果按键,则返回非0,否则返回0
unsignedcharkeyGet(void);
//读取按键值,如果没有按键则等待到按键为止
voidkeyPut(unsignedcharucKeyVal);
//保存按键值ucKeyVal到按键缓冲队列末
voidkeyBack(unsignedcharucKeyVal);
//退回键值ucKeyVal到按键缓冲队列首
定义函数体文档KEY.C,如下:
#include“key.h”
#defineKeyBufSize16//定义按键缓冲队列字节数
unsignedcharKeyBuf[KeyBufSize];
//定义一个无符号字符数组作为按键缓冲队列。
该队列为先进
//先出,循环存取,下标从0到KeyBufSize-1
unsignedcharKeyBufWp=0;
//作为数组下标变量,记录存入位置
unsignedcharKeyBufRp=0;
//作为数组下标变量,记录读出位置
//如果存入位置与读出位置相同,则表明队列中无按键数据
unsignedcharkeyHit(void)
{if(KeyBufWp==KeyBufRp)return(0);
elsereturn
(1);
unsignedcharkeyGet(void)
{unsignedcharretVal;
//暂存读出键值
while(keyHit()==0);
//等待按键,因为函数keyHit()的返回值为0表示无按键
retVal=KeyBuf[KeyBufRp];
//从数组中读出键值
if(++KeyBufRp>
=KeyBufSize)KeyBufRp=0;
//读位置加1,超出队列则循环回初始位置
return(retVal);
voidkeyPut(unsignedcharucKeyVal)
{KeyBuf[KeyBufWp]=ucKeyVal;
//键值存入数组
if(++KeyBufWp>
=KeyBufSize)KeyBufWp=0;
//存入位置加1,超出队列则循环回初始位置
/*****************************************************************************************
由于某种原因,读出的按键,没有用,但其它任务要用该按键,但传送又不方便。
此时可以退回按键队列。
就如取错了信件,有必要退回一样
******************************************************************************************/
voidkeyBack(uns
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 课程 笔记