学习笔记(观看小蜜蜂【DS18B20以前】与西风课程讲解)+自己以前对普中款51单片机学习理解
38译码器与74HC573锁存器的配合使用(逻辑门起重要作用)
38译码器:(节约IO口) 通过25-273位引脚去控制8位,被选中的位号被置为高电平1;只好使用到Y4-Y7这4位,选中Y4时,P27=1,P26=0,P25=0;选中Y5时,P27=1,P26=0,P25=1;以此类推。
74HC573锁存器:(增添锁存器【廉价】,使引脚复用,节约IO口) 当LE所处引脚为低电平0时锁存器打开,可以修改内容,为高电平1时锁存器关闭,无法修改内容。(而译码器选中的位号被置为高电平,于是需要用到逻辑门(或非门))
LED模块
先通过38译码器选择Y4位,再给P0引脚赋值
共阳极的LED灯,给相应位号提供低电平即可点亮该位号的LED灯,闪烁使用延时,流水灯使用延时+移位
蜂鸣器与继电器模块
注意调节跳线帽使其处于蜂鸣器、继电器板块
蜂鸣器:(引脚为低电平时蜂鸣器发声)
继电器:(引脚为低电平时继电器吸合,继电器亮灯)
ULN2003(达林顿管)是7路反向器电路,即当输入端为高电平时,ULN2003输出端为低电平;当输入端为低电平时,ULN2003输出端为高电平。
所以要选中蜂鸣器、继电器使其工作,即需使相应位号置高电平即可
P0赋值:继电器工作: 0x10;蜂鸣器工作:0x40。
数码管模块
先用38译码器选中Y6对应的锁存器,为P0引脚赋值选中想要使用的第几位数码管,再将译码器选中Y7对应的锁存器,为P0引脚赋值点亮想要使用的几段LED。
位选时,P0赋值为高电平即为选中;段选时,P0赋值为低电平即为点亮对应LED(共阳极)
使用数码管时很重要的步骤是消影和防闪烁;延时过短可能造成一个数码管内重影,分辨不清;延时过长则会导致数码管内数字闪烁。由于是共用P0引脚,则需要在段选或位选前清空P0引脚的值,将其全赋值为高电平(消影效果最好)。
静态数码管是选用一管、一个字符;动态数码管是选用多管、多个字符。
按键模块
注意跳线帽接的是独立按键还是矩阵按键。
独立按键
将J5上的跳线帽接在23位号上,P30至P33默认为高电平,当其为低电平时则为对应按键被按下。
判断按键被按下,需要注意按键需要防误触(添加一小段延时再进行判断),最后还需要将按键锁定到被按下的情况(直到松手)。每个按键判断被按下的语句如下:
矩阵按键
将J5上的跳线帽接在12位号上,使用行扫描与列扫描判断被按下按键的行与列,从而得知被按下按键的具体位号。
先定义位号:(头文件reg52.h内没有P4引脚的地址,则使用下面方法定义P4引脚时,需要先使P4指向其引脚地址【sfr P4 = 0xc0】)
列扫描
先将行置0,列置1:
当某一列被按下时,则该列为0,即可确认第几列按键被按下。如下:(仍需要进行防误触检测)
为按键变量赋值,第一列为0,第二列为1……第四列为3。
行扫描
将列置0,行置1:
当某一行被按下时,则该行为0,即可确认第几行按键被按下。如下:(仍需要进行防误触检测)
为按键变量赋值,第一行值+0,第二行值+4……第四行值+12。
完成行列扫描后的按键变量即为最终被按下的按键值(0-15)
中断系统
外部中断
注意在使用外部中断用到按键的过程中,一定先要将跳线帽接到独立按键上。
分为外部中断0与外部中断1,当满足中断条件(下降沿或低电平)时触发中断,程序从原来执行的程序转去执行终端服务函数。中断需写中断初始化函数以及中断服务函数。
中断初始化函数:
外部中断0的初始化函数意思:
1、打开总中断
2、打开外部中断0
3、确定中断触发方式(1为下降沿触发,0为低电平触发)
外部中断1的初始话函数同理
大致与(普中款)51单片机的中断系统相同
中断服务函数:
中断服务函数一定要在()后加上中断入口号,才能在触发中断时进入到中断服务函数进行中断处理。(外部中断0的中断入口号为0,外部中断1的中断入口号为2)同普中款51单片机:
定时(计数)器中断
单片机的外部晶振为12MHz,定时计数器有16位,分为高8位与低8位,工作模式最大的定时时间为65535us。当定时计数器出现溢出(满了)则会触发中断,进行服务函数,定时计数器的初始化函数以及服务函数都需要对高低8位赋值。
高低8位赋值原则:THx = (65535 - 想要的定时时间)/256;TLx = (65535 - 想要的定时时间)%256。
TMOD定时计数器模式控制寄存器
该寄存器不能进行位寻址,只能字节寻址,所以需要一次性给其赋值十六进制。
TMOD寄存器:GATE,C/T,M1,M0,GATE,C/T,M1,M0。高4位定义定时/计数器1的模式;低4位定义/定时计数器0的模式。
GATE:为0时,由TR0和TR1来启动定时器;为1时,由外部中断引脚INT0和INT1来启动定时器。
C/T:为0时,是定时功能;为1时,是计数功能。
M1,M0:工作方式设置:
00:13位定时/计数器
01:16位定时/计数器,最大计数值为65535
10:自动重装8位定时/计数器,最大计数值为255
11:T0分为两个独立的8位定时/计数器;T1停止计数
使用
初始化函数:
1、开总中断
2、开定时计数器中断
3、开启定时计数器
4、设置定时计数器工作功能与模式
5、定时或计数
中断服务函数:
开始就重置定时或计数,设置变量选取时间,注意写上中断入口号。
PWM脉宽调制信号的发生
调整一个脉冲周期内的高低电平的占空比,从而调整PWM。
PWM脉冲为100Hz,一个周期有10ms,将其分为100份,则1份时间为100us,则可将100份分为高低电平,利用占空比则可以控制脉宽。
脉宽调制常与定时计数器定配合使用从而达到调制脉宽的目的。
如上为利用脉宽调制LED光强的定时计数器部分函数,pwm_dute为占空比档次(0-4档),通过按键控制档次增减(未写),由于一个pwm周期被分为了100份,则count的最大值为100,当档次越高,光强越大,则LED点亮的占空比更大。
串行通信
数据一位接着一位地顺序发送或接收。常见有SPI、I2C、UART……大多数情况下,串口通信指的就是UART(最常用)。串行通信有单工(只能发或只能收数据)、半双工(既可以收数据,也可以发数据,但不能同时收发)、全双工(可以同时完成数据的收发)三种。
串行通信分为同步和异步两种方式。同步:使用同一个时钟,以数据块为单位传送数据;异步:每个设备有各自的时钟信号,通信中双方的波特率要保持一致,以字符为单位进行数据帧传送,一次传送一帧。
波特率
串口每秒传输的位数就是波特率,51单片机中常用定时器1的工作模式2(8位自动重装)来产生波特率,TL1为脉冲计数寄存器,TH1为自动重装寄存器,当计数到最大值溢出时,TH1的值自动装到TL1中。
波特率计算公式:波特率 = (2^SMOD /32)x T1的溢出率
12M或11.0952M晶振要产生9600BPS的波特率:
SMOD = 0时,参数为0xfd。
SMOD = 1时,参数为0xfa。
SBUF寄存器
串行发送时,CPU向SBUF写入数据,此时99H表示发送缓存SBUF。
串行接收时,CPU从SBUF读出数据,此时99H表示接收缓存SBUF。
发送数据:
将要发送的数据/变量赋值给SBUF,内核自动将数据发送出去,内容发生完成后,会将TI标志位置1。
接收数据:
内核从串口接收到一个完整数据后,会将RI标志位置1,此时直接读取SBUF的值即完成数据的接收。
数据发送完毕或接收完毕都会进入串口中断,此时要注意是完整发送数据后产生的中断还是完整接收到数据后产生的中断。
串口控制寄存器
SCON串口控制寄存器:SM0、SM1、SM2、REN、TB8、RB8、TI、RI
TI:发送完成中断标志位(需手动软件清除)
RI:接收完成中断标志位(需手动软件清除)
RB8:发送数据的第8位。(奇偶校验)(用不到为0)
TB8:接收数据的第8位。(奇偶校验)(用不到为0)
REN:为1时允许接受;为0时禁止接收
SM2:模式二与模式三时才使用到,主要使用模式一。
SM0、SM1工作模式:
00:同步移位寄存器(波特率:fosc/12)
01:8位的UART(波特率:可变)【大部分情况】
10:9位的UART(波特率:fosc/32或fosc/64)
11:9位的UART(波特率:可变)
使用
串口通信初始化函数:
1、打开总中断
2、打开串口中断
3、开启定时计数器1
4、设置定时器1工作在自动重装8位定时/计数器模式(10)
5、设置SCON串口控制寄存器
6、使辅助寄存器置0(蓝桥杯单片机加)
7、
发送字节函数:
将要发送的数据传给SBUF寄存器,然后在数据发送完后对发送标志位进行手动清零。
通信中断服务函数:
通信中断入口号为4,判断接受标志位,是否完全接收,并进行手动清零。
发送字符串
使用指针做形参指向想要发送字符串,一次一次的发送单个字符,在串口助手中选择文本模式。
DS18B20
简介
一种单总线的外设(传感器),有严格的时序要求。
使用流程
1、复位DS18B20。
2、写入字节0xcc,跳过ROM指令(ROM空间有64位,保存64个id,单片机上只有一个DS18B20,一个id,则可以直接跳过ROM指令检测,直接开始温度转换)。
3、写入字节0x44,开始温度转换。
4、写入转换延时(温度转化是需要时间的,一般是700~900ms)【要完成温度转换再读取结果】
5、再次复位DS18B20。
6、写入字节0xcc,跳过ROM指令。
7、写入字节0xbe,读取高速暂存器(温度转换完后将值存入高速暂存器【9个字节】的第0字节(低8位)与第1字节(高8位))。
8、复位DS18B20,结束转换读取。
9、整合高八位与第八位(整合成16位)。
10、温度数据的正负处理。
步骤如下:(所调用函数均为赛点资源包内的单总线程序内的代码)
DS18B20的数据处理
DS18B20以16位带符号位扩展的二进制补码形式读出,其中低4位为小数部分,中间7位为整数部分,高5位为符号位。
DS18B20的分辨率为0.0625,当读出的数据为正时,将整合的16位直接乘以0.0625;当读出的数据为负时,则需将整合的16位进行取反加一,再乘以0.0625。
大致判断读取温度是否成功
DS18B20在上电复位时,温度寄存器中的值为0x0550,即85℃,若读出数据在80多℃时则表明可能读取温度失败,因为读取的是一个默认值。
注意
第一次写时失败,数码管显示0,未读出温度,原因是板载芯片的周期是1T,而赛点的代码的周期是12T。解决方案:可以将单总线底层代码里面用到的延时乘以10倍,即可正确读出。
DS1302
简介
一款时钟芯片,简单的串行接口与单片机进行通信,电路提供年、月、日、日期、时、分、秒的信息,每月天数与闰年天数可自动调整(2100年以前的)。对时序要求较高
有三个接口:RES(复位),I/O(数据线),SCLK(串行时钟)。
使用
可以在赛点资源包内找到DS1302相应的代码;自己需要写初始化代码(起始时间自己设定)跟读取当前时间的代码
起始代码:
先调用写入字节函数,去向地址(写)0x8e;将写保护位置0,打开寄存器可以进行写入操作。再根据需求去向地址(上图时、分、秒),写入起始值。再关闭写保护位。
读取数值:
去到相应的地址,用数组去承载其值(时、分、秒)。
显示数值:
将读取的值显示到数码管上。读到的值如0x58,则对应分为58分,对应秒为58秒。
AD/DA转化
PCF8591:
地址: 前四位固定,一条I2C总线上可以挂多个PCF8591,所以有选择地址位。但蓝桥杯单片机上仅有一个PCF8591,故而3位地址位全为0即可。最后一位确定是对其读消息还是写消息。
控制字节:控制字节存放在控制寄存器中,总线操作时为主控制器发送的第二字节。
D1、D0:A/D通道编号,00-11表示通道0-3
D2:自动增益选择(有效位为1)
D3:固定不变(0)
D5、D4:模拟量输入选择,00为四路单输入,01为三路差分输入,10为单端与差分配合输入,11为模拟输出允许有效
D6:A/D转换允许位,为0时允许模拟输出
D7:固定不变(0)
读光敏电阻:0x41,读滑动变阻器:0x43
I2C总线:
在传输数据过程中存在三种类型信号(开始、结束、应答)
开始信号:SCL为高,SDA由高向低跳变
结束信号:SCL为高,SDA由低向高跳变
时序图:
应答信号:SCL为高,读取SDA,为低电平表示产生应答(ACK),高电平表示非应答(NACK)
官方有给I2C底层代码。
A/D转化:
将模拟量转化为数字量
A/D转换周期总是在发送一个有效的读模式地址到PCF8591设备后开始的;即本次读取的数据是上一次转化完成的数据。
流程:(读取模拟量的过程)
1、I2C开始信号
2、写PCF8591地址(0x90)【写数据】
3、等待PCF8591回应
4、输入控制字节(通过通道)选择读取的模拟量
5、等待主机响应
6、I2C开始信号(开始两次原因是一次是写,一次是读)
7、写PCF8591地址(0x91)【读取】
8、等待PCF8591回应
9、接收模拟量
10、主机发送非应答
11、I2C结束信号
D/A转化:
将数字量转化为模拟量
流程:(转化数字量的过程)
1、I2C开始信号
2、写PCF8591地址(0x90)【写数据】
3、等待PCF8591回应
4、输入控制字节(0x4x)【使能够模拟输出】
5、等待PCF8591回应
6、写DAC的值
7、等待PCF8591回应
8、I2C结束信号
注意
若要同时将光敏电阻与滑动变阻器的模拟信号转化成数字信号,直接将读取值互换即可(光敏电阻的读取值是滑动变阻器的地址,滑动变阻器读取的值是光敏电阻的地址)。因为A/D转化的周期问题,本次读取的数据是上一次转化完成的数据。
AT24C02
原理图:
建议地址:
0xa0(写),0xa1(读)
写入:(一页内最多写8个字节)
往固定的地址里面写入固定的数据:
1、I2C开始信号
2、选择EEPROM芯片,确定写模式(0xa0)
3、等待EEPROM回应
4、写入要存储的数据地址(8的倍数,保证每页存储数据最大【8个字节】)
5、等待EEPROM回应
6、利用循环将信息写入(每次写入的数据最好8个)
7、I2C结束信号
void EEPROM_Write(unsigned char *EEPROM_String,unsigned char addr,unsigned char num)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
while(num--)
{
IIC_SendByte(*EEPROM_String++);
if(num)
IIC_SendAck(0);
else
IIC_SendAck(1);
}
IIC_Stop();
}
读取:
1、I2C开始信号
2、选择EEPROM芯片,确定写模式(0xa0)
3、等待EEPROM回应
4、写入要存储的数据地址(8的倍数,保证每页存储数据最大【8个字节】)
5、等待EEPROM回应
【以上为选择地址从哪一页开始读】
6、I2C开始信号
7、选择EEPROM芯片,确定读模式(0xa1)
8、等待EEPROM回应
9、接收读取的信息
10、I2C结束信号
void EEPROM_Read(unsigned char *EEPROM_String,unsigned char addr,unsigned char num)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
while(num--)
{
*EEPROM_String++ = IIC_RecByte();
if(num)
IIC_SendAck(0);
else
IIC_SendAck(1);
}
IIC_Stop();
}
一个保存键用于写入。
超声波模块
跳线帽接13、24。
原理
发射端发射信号(8个40MHz的方波信号)出去,遇见障碍物后信号返回回来,被接收端收到,中途时间*340/2=距障碍物距离。
使用
发射端发送信号:(8次40MHz方波)
读取接收端:(读取接收时间,换算为长度)
1、打开定时计数器1,配置计时模式,并不影响定时计数器0(0x0f)
2、复位计数值
3、发送超声波信号
4、开启定时计数器1
5、等待接受返回信号和定时器溢出
6、定时器是否溢出判断并返回值
NE555
需要连接上NET_SIG引脚与P34引脚以测频率。(频率:一秒钟内P34引脚产生了多少次上升沿或下降沿)【需要计数】
计数模式,令TMOD寄存器内的C/T位为1。