基础知识(总)
预备知识📖
一、单片机基本常识和学习习惯
一、点亮一个IED灯
1.IED
原理图

原理
低电平灯亮
实践代码
以下代码跑马灯均接到P1口
-
点亮第一个灯
#include<reg52.h> sbit D = P1^0; //点亮第一个灯 void main() { D = 0; } -
总线点亮第二个灯
#include<reg52.h> sbit D = P1^0; //总线点亮第二个灯 void main() { P1 = 0xFD; /* D7 D6 D5 D4 D3 D2 D1 D0 1 1 1 0 1 1 1 1 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0 1 1 1 1 1 1 0 1 */ } -
依次点亮各个灯
#include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit D = P1^0; /** * 0xFE 1111 1110 最低位为0,即亮最低位对应的灯 * 0xFD 1111 1101 * 0xFB 1111 1011 * 0xF7 1111 0111 * 0xEF 1110 1111 * 0xDF 1101 1111 * 0xBF 1011 1111 * 0x7F 0111 1111 * 可以看到0从最低位移动到最高位,实现了依次点亮 */ uchar array[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //1111 11110 -->0111 1111 uint a = 0; //依次点亮各个灯 void main() { int i = 0; while(1) { for (i = 0; i<8; i++) { a = 5100; P1 = array[i]; //sec = 0.4999s while(a--);//延时 } } } -
灯闪烁
#include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit K10 = P1^0; uint a ; //灯闪烁 void main() { while(1) { a = 50000; K10 = 0; while(a--);//延时 a = 50000; K10 = 1; while (a--); } } -
用
_crol_()函数实现流水灯的依次点亮-
_crol_()函数在#include<intrins.h>中,函数原型是unsigned char _crol_(unsigned char c,unsigned char b),表示变量c左移b位 -
#include<intrins.h>中还有![]()
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int uchar temp = 0xFE;//中间变量 void delay();//函数声明 //用_crol_()函数实现流水灯的依次点亮 void main(){ while(1) { P1 = temp; temp = _crol_(temp ,1);//中间变量左移 delay(); } } //延时函数 void delay() { uint x,y; //100 * 570 for (x =100; x>0; x--) for (y = 570; y>0; y--); } -
2.蜂鸣器
原理图

原理
P00 为高电平时,Q2导通,蜂鸣器响;
(有的单片机P00为低电平时,Q2导通,这取决于蜂鸣器的原理图)
实践代码
-
蜂鸣器伴随着流水等间断的闪
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int //定义变量 uchar temp = 0xFE;//中间变量 sbit beep = P3^4; //函数声明 void delay(); //蜂鸣器伴随着流水等间断的闪 void main() { while(1) { P1 = temp;//跑马灯接在P1口 beep = 1;//响 temp = _crol_(temp ,1);//中间变量左移 delay(); beep = 0;//不响 delay(); } } //延时函数 void delay() { uint x,y; //100*2000 for (x =100; x>0; x--) for (y = 570; y>0; y--); }
二、数码管
1.中央控制器(CPU)原理图

2.LED显示器原理图

引脚图

如果想要显示1,就得让b、c为1,所以段选码为0000 0110,即0x06;
如果想要显示2,就得让a、b、g、e、d为1,所以段选码为0101 1011,即0x5B;
其他数字同理。
原理
-
锁存端是高电平的时候,输入端和输出端是相通的;
-
锁存端是低电平的时候,输入端和输出端是断开的,输出端保持原来的值。
-
P13口是数码管总开关,P15是位选开关,P14是端选开关
-
位选是选数字显示的位置,段选是选具体的数字
具体过程(数码管从左往右第二位显示“2”)
-
定义
sbit dula = P1^3;,sbit wela = P1^4;;(P1.3、P1.4口分别是控制段选和位选的的IO口) -
首先数码管总开关打开
K1 = 0;,让P0 = 0xFD;,然后打开位选开关wela = 1;,这样P0的值就会送入,wela = 0;开关关闭,P0的值被”关起来“了(锁存),这样就确定了数码管在从左往右第二位显示数字 -
P0 = 0x5B;,然后打开段选开关dula = 1;,这样P0的值就会送入,dula = 0;开关关闭,P0的值锁存,这样就确定了显示的数字是“2”。
3.display
博主自己定义的、常用来数码管显示的函数
数码管显示定义成函数有助于功能模块化、清晰化
//数码管显示
void display(int position, int n)
{
//异常检查
if(n < 0 || n > 17) return ;
if(position < 0 || position > 7) return ;
//“总开关”打开
K13 = 0;
//消隐
dula = 1;
P0 = 0x00;
dula = 0;
//位选
P0 = positions[position];
wela = 1;//高电平数据直通
wela = 0;//低电平锁存
//段选
P0 = table[n];
dula = 1;
}
段选码、位选码
- 段选码 0~9 + A~F + "-" + "." 表示数码管显示的内容
- 位选码 1-8 表示数码管显示内容的位置
//段选
uchar table[18]=
{
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x80,0x40
};//0x80是小数点,0x40是“-”
//位选
uchar positions[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
实践代码
-
点亮第一个数码管,并让其保持常亮
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int //定义变量 sbit K1 = P1^3; sbit K2 = P1^4; sbit K3 = P1^5; //点亮第一个数码管,并让其保持常亮 void main() { K1 = 0;//打开数码管 //位选 K3 = 1;//高电平数据直通 P0 = 0xFE;//1111 1110 K3 = 0;//低电平锁存 //段选 P0 = 0x06; //0000 0110 K2 = 0; while(1); } -
依次循环0~9
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define length 10 //变量定义 sbit K1 = P1^3; sbit K2 = P1^4; sbit K3 = P1^5; int i = 0; int j = 0; //段选 0~9 uint array[length] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //位选 1~8 uchar position[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //函数声明 void delay(); //依次循环0~9 void main() { K1 = 0;//打开数码管 while(1) { for (i = 0; i < length; i ++) { if (j >= 8) j = 0; //位选 K3 = 1; P0 = position[j]; K3 = 0; //段选 P0 = array[i]; K2 = 1; K2 = 0; j ++; delay(); } } } //延时 void delay() { uint x,y; //100 * 570 for (x =100; x>0; x--) for (y = 570; y>0; y--); } -
使用display函数显示数字
#include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define length 9 //变量定义 sbit K13 = P1^3; sbit dula = P1^4; sbit wela = P1^5; int i = 0; //段选 uint table[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //位选 uchar positions[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //函数声明 void delay(); void display(int position, int n); //依次循环0~9 void main() { while(1) { for (i = 0; i < length; i ++) { display(i,i);//数码管显示 delay();//延时 } } } //延时函数 void delay() { uint x,y; //100 * 570 for (x =100; x>0; x--) for (y = 570; y>0; y--); } //数码管显示 void display(int position, int n) { //异常检查 if(n < 0 || n > 17) return ; if(position < 0 || position > 7) return ; //“总开关”打开 K13 = 0; //消隐 dula = 1; P0 = 0x00; dula = 0; //位选 P0 = positions[position]; wela = 1;//高电平数据直通 wela = 0;//低电平锁存 //段选 P0 = table[n]; dula = 1; }
三、中断
四、定时
五、按键
六、D/A A/D转换器及其单片机接口
七、串行口的工作原理及其应用
1、SCON

2、TI、RI

3、波特率


代码部分
1、通过串口调试助手发送数据并显示到跑马灯上
#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
init();
while(1)
{
if(RI == 1)
{
RI = 0;
P2 = SBUF;
}
}
}
//初始化
void init()
{
TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
TH1 = 0XFD;
TL1 = 0XFD;
SM0 = 0;
SM1 = 1;
REN = 1;
TR1 = 1;
}
2、通过串口调试助手发送数据并显示到跑马灯上
(利用到了串行口中断)
#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
init();
while(1);
}
//窗口中断
void ser() interrupt 4
{
RI = 0;
P2 = SBUF;
}
//初始化
void init()
{
TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
/*设置波特率位9600 */
TH1 = 0XFD;
TL1 = 0XFD;
/*8位异步收发,波特率可变*/
SM0 = 0;
SM1 = 1;
REN = 1;//允许串行口接受数据
TR1 = 1;//打开定时器1
EA = 1;//总中断允许
ES = 1;
}
3、自发收
#include<reg52.h>
//函数声明
void init();
//主函数
void main()
{
init();
while(1);
}
//串口中断
void ser() interrupt 4
{
RI = 0;
P2 = SBUF;
SBUF = P2;
TI = 0;
}
//初始化
void init()
{
TMOD = 0X20;//设置定时器1为8位的常数自动装载的定时器/计数器
/*设置波特率位9600 */
TH1 = 0XFD;
TL1 = 0XFD;
/*8位异步收发,波特率可变*/
SM0 = 0;
SM1 = 1;
REN = 1;//允许串行口接受数据
TR1 = 1;//打开定时器1
EA = 1;//总中断允许
ES = 1;
}


浙公网安备 33010602011771号