百度seo 站长工具,重庆seo1,用vue.js做网站的好处,如何把网站做跳转浏览器链接为学习嵌入式做准备#xff0c;重新拿起51单片机学习。此贴为学习笔记#xff0c;仅记录易忘点#xff0c;实用理论基础#xff0c;并不是0基础。 资料参考#xff1a;清翔零基础教你学51单片机 51单片机学习笔记1. C语言中的易忘点1.1 数据类型1.2 位运算符1.3 常用控制语…为学习嵌入式做准备重新拿起51单片机学习。此贴为学习笔记仅记录易忘点实用理论基础并不是0基础。 资料参考清翔零基础教你学51单片机 51单片机学习笔记1. C语言中的易忘点1.1 数据类型1.2 位运算符1.3 常用控制语句1.4 C51程序的基本结构2.电子电路基础2.1 电平2.2 I/O引脚2.2.1 P3口的第二用途2.3 电子元器件2.3.1 电阻2.3.2 电容2.3.3 蜂鸣器2.3.3.1 判断有源蜂鸣器和无源蜂鸣器2.3.3.2 驱动蜂鸣器2.3.4 常见符号3.单片机 基础知识点3.1 单片机最小系统3.2 基本时序4. 51单片机基础例程I/O外设4.1 点亮LED灯4.1.1编程知识点4.1.1.1 位定义4.1.2 编程4.2 LED闪烁4.2.1 编程知识点4.2.1.1 变量作用域4.2.1.2 软件延时4.2.2 编程4.3 流水灯4.3.1 编程知识点4.3.1.1宏定义4.3.1.2 函数的定义4.3.1.3 延时函数4.3.1.4 循环移位函数4.3.1.4.1 循环移位函数与左移和右移运算符的区别4.3.2 编程4.4 数码管静、动态显示4.4.1 单个数码管--静态显示原理4.4.2 74HC573锁存器工作原理4.4.3 多个数码管--动态显示原理4.4.4 编程知识点4.4.4.1 数组的定义与引用4.4.5 编程4.4.5.1 共阴极数码管静态显示只亮一个数码管4.4.5.2 共阴极数码管动态显示4.5 非编码键盘4.5.1 独立键盘4.5.2 矩阵键盘1.硬件接线2.扫描4.5.3 编程知识点4.5.3.1程序去抖4.5.3.2 开关语句4.5.4 编程4.5.4.1 独立键盘4.5.4.2 矩阵键盘1. C语言中的易忘点
1.1 数据类型 1.2 位运算符
~ 按位取反左移右移按位与
^ 按位异或
| 按位或异或相同取0不同取1.
1.3 常用控制语句
条件 if 循环while 、 for 开关switch
1.4 C51程序的基本结构
#include reg52.h //包含51单片机头文件void main() //主函数
{}C语言设置的程序中只允许有一个main函数。程序总是从main函数开始运行的main函数是void型无返回值。
2.电子电路基础
2.1 电平
数字电路中只有两种电平高电平和低电平。 高电平5V 低电平0V
TTL电平规定高电平输出电压2.4V低电平输出电压0.4V 计算机串口使用的是RS232电平 高电平-12V 低电平12V Tips:单片机与计算机串口通信时需要使用电平转换芯片把RS232电平转为TTL电平后单片机才能识别。
2.2 I/O引脚 例程中 P0接LEDP2^3接蜂鸣器。
2.2.1 P3口的第二用途 2.3 电子元器件
2.3.1 电阻
常用的贴片电阻封装0402、0603、0805、1206、1210 贴片电阻读数参考贴片电阻上的字符是如何表示电阻的
103那么10是有效数字3表示10的3次方所以103表示的阻值就是10x10^{3}
1502,150是有效数字2表示10的2次方所以1502表示的阻值就是150*10^{2}
5R65.6Ω、R160.16Ω
01C就是10k2.3.2 电容
电容的作用储能滤波通交流隔直流旁路耦合补偿充放电等
1F法拉 1000000μF微法
1μF微法 1000nF纳法
1nF纳法 1000pF皮法2.3.3 蜂鸣器
2.3.3.1 判断有源蜂鸣器和无源蜂鸣器
可以用万用表电阻档Rxl档测试:用黑表笔接蜂鸣器 引脚红表笔在另一引脚上来回碰触如果触发出咔、咔声的且电阻只有8Ω(或16Ω)的是无源蜂鸣器;如果能发出持续声音的且电阻在几百欧以上的是有源蜂鸣器。
2.3.3.2 驱动蜂鸣器
由于蜂鸣器的工作电流一般比较大以致于单片机的I/O 口是无法直接驱动的所以要利用放大电路来驱动一般使用三极管来放大电流就可以了。 除此之外还有一些其他驱动方式PWM 输出口直接驱、I/O 口定时翻转电平驱动蜂鸣器方式
2.3.4 常见符号 3.单片机 基础知识点
3.1 单片机最小系统
电源 给整个系统提供能量 单片机芯片 运行程序/处理数据 晶振电路 给单片机工作提供节拍 复位电路 单片机上电时需要复位使程序从头开始运行
3.2 基本时序
振荡周期: 也称时钟周期, 是指为单片机提供时钟脉冲信号的振荡源的周期。
机器周期: 一个机器周期包含 12 个时钟周期。 在一个机器周期内, CPU可以完成一个独立的操作。
例如计算外部晶振频率为11.0592Mhz的单片机一个机器周期所需的时间 1/11.0592 * 12 ≈ 1.085μS 说明“1/(11.0592*1000000)”乘以106把Mhz转为hz再乘以“12”是12个时钟周期等于一个机器周期最终值为秒把这个单位为秒的值乘以106所得值约等于1.085微秒。
4. 51单片机基础例程I/O外设
例程中LED位共阳极 要点亮开发板上LED灯只需要控制P1口输出低电平即可 编程时给P1口赋值“0”
4.1 点亮LED灯
普通发光二极管工作压降为1.6v ~ 2.1 V。 工作电流为1~20mA 注意二极管需要上拉电阻。 否则电流(5V-2.1V)/0Ω电流无限大 有电阻后电流(5V-2.1V)/1kΩ,约等于3mA.
4.1.1编程知识点
4.1.1.1 位定义
关键字sbit 功能位定义 一般格式 sbit 标识符 地址值;
例如sbit LED1 P1^0; 注意地址值中P1的“P”必须为大写的P
4.1.2 编程
#include reg52.h //引用51头文件sbit LED1 P1^0; //位定义void main() //主函数
{LED1 0;//点亮P1.0上的LED
}4.2 LED闪烁
4.2.1 编程知识点
4.2.1.1 变量作用域
全局变量在函数体外定义的变量通常为全局变量作用范围从定义开始的整个程序局部变量在函数体内定义的变量通常为局部变量作用范围函数体内4.2.1.2 软件延时
软件延时例如
unsigned int i
i65535;
while(i);4.2.2 编程
实现P1口上所有LED闪烁
#include reg52.h//包含51头文件unsigned int i;//0~65535void main()//main函数自身会循环
{while(1)//大循环{P1 0; //点亮P1口8个LEDi 65535;while(i--);//软件延时P1 0xff;//1111 1111 熄灭P1口8个LEDi 65535;while(i--);//软件延时 }
} 按位取反 闪烁写法
#include reg52.hunsigned int i;//0~65535void main()//main函数自身会循环
{P1 0xff;//熄灭8位LEDwhile(1) //大循环{P1 ~P1; //使用按位取反运算符使LED闪烁i 65535;while(i--);//软件延时}
} 4.3 流水灯
4.3.1 编程知识点
4.3.1.1宏定义
理解成 用define/ typedef 取小名
#define uchar unsigned char
注意宏定义后面不能加分号它是预处理指令不是语句。其中用“uchar”直接替换了unsigned char 此时我们可以用uchar去定义变量类型如uchar i;等价于unsigned char i;
【C语言】typedef与define的区别
typedef我们可以为基本类型如int、float或自定义的结构体、联合体等定义新的名称。define定义常量、函数替换宏、条件编译等它的作用范围更为广泛。所有满足条件的宏定义在预处理阶段都会被替换为指定的文本。4.3.1.2 函数的定义
自定义函数一般格式为:
函数类型 函数名 形式参数表
{局部变量定义函数体语句
}4.3.1.3 延时函数
自定义函数延时函数delay(毫秒级)
void delay(unsigned int z)
{unsigned int x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
}给形参z赋值如延时100毫秒delay(100);
4.3.1.4 循环移位函数
标准库函数 intrins.h内部函数
字符型循环左移_crol_
字符型循环右移_cror_#include intrins.h
void test_crol (void) {unsigned char a;unsigned char b;a 0xFE; //1111 1110b _crol_(a,1); // b now is 0xFD 二进制为1111 1101
}4.3.1.4.1 循环移位函数与左移和右移运算符的区别
循环左移是把最高位移到最低位上 左移运算符是把最高位移除最低位补0
4.3.2 编程
实现流水灯一直左循环
#include reg52.h //包含51头文件
#include intrins.h //包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charuchar temp;//LED灯相关变量
/*
函数 delay(uint z)
参数 z 延时毫秒设定取值范围0-65535
返回值 无
描述 12T/Fosc11.0592M毫秒级延时
*/
void delay(uint z)
{uint x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
} void main()//main函数自身会循环
{temp 0xfe;P1 temp; //1111 1110 初值LED1亮delay(100);//毫秒级延时 100毫秒while(1){temp _crol_(temp, 1);//循环左移P1 temp;//移位完成后赋值给P1 每个一个灯点亮delay(100);//毫秒级延时 100毫秒}
} 4.4 数码管静、动态显示
4.4.1 单个数码管–静态显示原理
有共阳、共阴极例程使用共阴即b图左边。 共阴极数码码表
0x3F, //0
0x06, //1
0x5B, //2
0x4F, //3
0x66, //4
0x6D, //5
0x7D, //6
0x07, //7
0x7F, //8
0x6F, //9
0x77, //A
0x7C, //B
0x39, //C
0x5E, //D
0x79, //E
0x71, //F
0x76, //H
0x38, //L
0x40, //-
0x00, //熄灭4.4.2 74HC573锁存器工作原理
锁存器作用可以把数据输入端与输出端进行隔离或连接 左边D为输入右边Q为输出 输出口Q要想输出高低电平OE脚必须接GND。 LE脚为高时输出端Q随输入端D的数据而变化。 LE脚为低时输出端Q数据保持不变输入端D数据变化不会改变Q的数据。
4.4.3 多个数码管–动态显示原理
段选和位选
位选选择哪一个数码管亮
段选该数码管怎么亮数码管里的二极管怎么亮工作流 打开位选锁存器-指定某个数码管-关闭位选锁存器 打开段选锁存器-指定亮什么数字-关闭段选锁存器 因为扫描周期短所以肉眼可以看到多数码管同时亮 不同的数字。
4.4.4 编程知识点
4.4.4.1 数组的定义与引用
数组是一组有序数据的集合数组中每一个数据都是同一数据类型。数组中的元素可以用数组名和下标来唯一确定。
数组的一般格式定义如下
数据类型 数组名[常量表达式] {元素表}例如
unsigned char tabel[3] {0x3F, 0x06, 0x5B, };
P0 tabel[0]; //P0此时的值为0x3F4.4.5 编程
4.4.5.1 共阴极数码管静态显示只亮一个数码管
#include reg52.h
#include intrins.h#define uint unsigned int
#define uchar unsigned charsbit DU P2^6;//数码管段选
sbit WE P2^7;//数码管位选////毫秒级延时函数定义
//void delay(uint z)
//{
// uint x,y;
// for(x z; x 0; x--)
// for(y 114; y 0 ; y--);
//} void main()//main函数自身会循环
{WE 1;//打开位选锁存器P0 0XFE; //1111 1110 选通第一位数码管WE 0;//锁存位选数据DU 1;//打开段选锁存器P0 0X06;//0000 0110 显示“1”DU 0;//锁存段选数据while(1){}
} 4.4.5.2 共阴极数码管动态显示
#include reg52.h//包含51头文件
#include intrins.h//包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charsbit DU P2^6;//数码管段选
sbit WE P2^7;//数码管段选//共阴数码管段选表0-9
uchar code tabel[] {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};/*
函数 delay(uint z)
参数 z 延时毫秒设定取值范围0-65535
返回值 无
描述 12T/Fosc11.0592M毫秒级延时
*/
void delay(uint z)
{uint x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
} /*
函数 display(uchar i)
参数 i 显示数值取值范围0-255
返回值 无
描述 三位共阴数码管动态显示
*/
void display(uchar i)
{uchar bai, shi, ge;bai i / 100; //236 / 100 2shi i % 100 / 10; //236 % 100 / 10 3ge i % 10;//236 % 10 6//第一位数码管 P0 0XFF;//清除断码WE 1;//打开位选锁存器P0 0XFE; //1111 1110WE 0;//锁存位选数据DU 1;//打开段选锁存器P0 tabel[bai];//DU 0;//锁存段选数据delay(5);//第二位数码管P0 0XFF;//清除断码WE 1;//打开位选锁存器P0 0XFD; //1111 1101WE 0;//锁存位选数据DU 1;//打开段选锁存器P0 tabel[shi];//DU 0;//锁存段选数据delay(5);//第三位数码管P0 0XFF;//清除断码WE 1;//打开位选锁存器P0 0XFB; //1111 1011WE 0;//锁存位选数据DU 1;//打开段选锁存器P0 tabel[ge];//DU 0;//锁存段选数据delay(5);
}void main()//main函数自身会循环
{ while(1){display(236); //数码管显示函数}
} 4.5 非编码键盘
4.5.1 独立键盘
每个按键占用一个IO口当按键数量较多时IO口利用效率不高
但程序简单适用于所需按键较少的场合。按键一端与IO口连接另外一端接地。I/O进行检测 按键按下会被检测到低电平未按下被检测为高电平。
4.5.2 矩阵键盘
电路连接复杂但提高了IO口利用率软件编程较复杂。
适用于使用大量按键的场合。上图为4行和4列一共16个按键组成。
确定矩阵键盘上哪一个按键被按下可以采用列扫描和行扫描。
列扫描时先把接在列上面的所有IO口拉高接在行上的所有IO置低。
当其中有一列内任何一个按键按下那么整条列线都会被拉低。1.硬件接线
P3口的高4位P3.4~P3.7作为列线输出
P3口的低4位P3.0~P3.3作为行线输入uchar cord_l,cord_h;//声明列线和行线的值的储存变量P3 0xf0;//1111 00002.扫描
扫描分为两步列扫描和行扫描通过检测电平变化确定按键位置。 step1–列判断行线P3.0 ~ P3.7为0列线P3.4 ~ P3.7为1即P30xf0。 当四列中某一列被按下列线的对应的值就会改变。 cord_l P3 0xf0;// 只储存列线值 (f0的0作用无论行线是多少都不保存写0) 例2行2列的S11按下读到L0xd0图中从下P37往上P301101 0000step2–行判断在列判断后保留读到的列线值,行线值写1。即用读到的列线值 或 0x0f。
例0xd0|0x0f 1101 0000|00001111得到1101 1111
2行2列的S11按下导致P31的1变为0即变为1101 1101 0xdd
0xdd0x0f0x0d此为行线值P3 cord_l | 0x0f;cord_h P3 0x0f;// 只储存行线值(0f的0作用无论列线是多少都不保存写0)step3 列线值行线值
return (cord_l cord_h);//返回键值码4.5.3 编程知识点
4.5.3.1程序去抖 if(key_s3 0)//判断S3是否被按下{delay(20);//按键消抖if(key_s3 0){...while(!key_s3);//松手检测} }4.5.3.2 开关语句
switch 表达式
{case 常量表达式1 语句1breakcase 常量表达式2 语句2break}4.5.4 编程
4.5.4.1 独立键盘
实现按下开发板左下角S2按键数码管值1,最大到9按下S3按下值减一最小减到0
#include reg52.h
#include intrins.h#define uint unsigned int
#define uchar unsigned charsbit DU P2^6;//数码管段选
sbit WE P2^7;//数码管位选
sbit key_s2 P3^0;//独立按键S2
sbit key_s3 P3^1;//独立按键S3
uchar num;//数码管显示的值//共阴数码管段选表0-9
uchar code tabel[] {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};//毫秒级延时函数定义
void delay(uint z)
{uint x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
} void main()//main函数自身会循环
{ num 0; WE 1;//打开位选锁存器P0 0XFE; //1111 1110WE 0;//锁存位选数据while(1){if(key_s2 0)//判断S2是否被按下{delay(20);//按键消抖if(key_s2 0){if(num ! 9)//如果值不等于9则1功能把值限定为小于9num;while(!key_s2);//松手检测} }if(key_s3 0)//判断S3是否被按下{delay(20);//按键消抖if(key_s3 0){if(num 0) //如果大于0则执行减一num--;while(!key_s3);//松手检测} }//松手之后刷新显示DU 1;//打开段选锁存器P0 tabel[num];//DU 0;//锁存段选数据}
} 4.5.4.2 矩阵键盘
实现矩阵键盘
#include reg52.h
#define uchar unsigned char
#define uint unsigned int
sbit we P2^7;
sbit du P2^6;
uchar code leddata[]{ 0x3F, //00x06, //10x5B, //20x4F, //30x66, //40x6D, //50x7D, //60x07, //70x7F, //80x6F, //90x77, //A0x7C, //B0x39, //C0x5E, //D0x79, //E0x71, //F0x76, //H0x38, //L0x37, //n0x3E, //u0x73, //P0x5C, //o0x40, //-0x00, //熄灭0x00 //自定义};
void delay(uint z)
{uint x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
}uchar KeyScan() //带返回值的子函数
{uchar cord_l,cord_h;//声明列线和行线的值的储存变量P3 0xf0;//1111 0000if( (P3 0xf0) ! 0xf0)//判断是否有按键按下{delay(5);//软件消抖if( (P3 0xf0) ! 0xf0)//判断是否有按键按下{cord_l P3 0xf0;// 储存列线值P3 cord_l | 0x0f;cord_h P3 0x0f;// 储存行线值while( (P3 0x0f) ! 0x0f );//松手检测return (cord_l cord_h);//返回键值码} }}void KeyPro()
{switch( KeyScan() ){//第一行键值码case 0xee: P0 leddata[0]; break;case 0xde: P0 leddata[1]; break;case 0xbe: P0 leddata[2]; break;case 0x7e: P0 leddata[3]; break;//第二行键值码case 0xed: P0 leddata[4]; break;case 0xdd: P0 leddata[5]; break;case 0xbd: P0 leddata[6]; break;case 0x7d: P0 leddata[7]; break;//第三行键值码case 0xeb: P0 leddata[8]; break;case 0xdb: P0 leddata[9]; break;case 0xbb: P0 leddata[10]; break;case 0x7b: P0 leddata[11]; break;//第四行键值码case 0xe7: P0 leddata[12]; break;case 0xd7: P0 leddata[13]; break;case 0xb7: P0 leddata[14]; break;case 0x77: P0 leddata[15]; break;}
}void main()
{we 1;//打开位选P0 0;//八位数码管全显示we 0;//锁存位选du 1;//打开段选端P0 leddata[22];while(1){KeyPro();//提取键值码并且送不同数值给数码管显示}
}实现按下矩阵键盘和独立键盘任意键数码管显示相应数值初始显示“-”横
#include reg52.h//包含51头文件
#include intrins.h//包含移位标准库函数头文件#define uint unsigned int
#define uchar unsigned charsbit DU P2^6;//数码管段选
sbit WE P2^7;//数码管段选
uchar num;//数码管显示的值
uchar KeyValue 20;//按键值 显示-//共阴数码管段选表
uchar code tabel[] {
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F H L
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x76, 0x38,
//n u - 熄灭
0x37, 0x3E, 0x40, 0x00 };/*
函数 delay(uint z)
参数 z 延时毫秒设定取值范围0-65535
返回值 无
描述 12T/Fosc11.0592M毫秒级延时
*/
void delay(uint z)
{uint x,y;for(x z; x 0; x--)for(y 114; y 0 ; y--);
}
/*
函数 KeyScan()
参数 无
返回值 无
描述 4*4矩阵键盘与独立键盘扫描
按键按下KeyValue全局变量值发生相应变化
*/
void KeyScan()
{//4*4矩阵键盘扫描P3 0XF0;//列扫描if(P3 ! 0XF0)//判断按键是否被按下{delay(10);//软件消抖10msif(P3 ! 0XF0)//判断按键是否被按下{switch(P3) //判断那一列被按下{case 0xe0: KeyValue 0; break;//第一列被按下case 0xd0: KeyValue 1; break;//第二列被按下case 0xb0: KeyValue 2; break;//第三列被按下case 0x70: KeyValue 3; break;//第四列被按下 }P3 0X0F;//行扫描switch(P3) //判断那一行被按下{case 0x0e: KeyValue KeyValue; break;//第一行被按下case 0x0d: KeyValue KeyValue 4; break;//第二行被按下case 0x0b: KeyValue KeyValue 8; break;//第三行被按下case 0x07: KeyValue KeyValue 12; break;//第四行被按下 }while(P3 ! 0X0F);//松手检测 }}P3 0XFF;//独立按键扫描if(P3 ! 0XFF){delay(10);//软件消抖10msif(P3 ! 0XFF){switch(P3) //判断那一行被按下{case 0xfe: KeyValue 16; break;//S2被按下case 0xfd: KeyValue 17; break;//S3被按下case 0xfb: KeyValue 18; break;//S4被按下case 0xf7: KeyValue 19; break;//S5被按下 }while(P3 ! 0XFF);//松手检测 } }}void main()//main函数自身会循环
{WE 1;//打开位选锁存器P0 0XFE; //1111 1110WE 0;//锁存位选数据DU 1;//打开段选锁存器while(1){KeyScan();//20个按键键盘扫描P0 tabel[KeyValue];//显示按键值}
}