蓝桥杯单片机知识大全

蓝桥杯单片机笔记

                                                                      ---山东科技大学电子信息工程22级杰小韦

前言

        本人14届蓝桥杯单片机组国二

        蓝桥杯编程题85分,选择题15分,选择题包括的知识点太广了,对于大部分同学来说,很难去学完,不过省赛里,编程接近满分就是省一,国赛编程题接近满分就是国二,所以选择题我们完全可以不看。

        要想拿省一,我们需要把所有外设学完,背代码,写至少5道真题。刚学完写第一套题的时候会很困难,后面就很顺利了(我第一套题写了5天)

1.入门

2.LED

3.蜂鸣器和继电器

4.数码管

5.初始化函数封装

6.按键

独立按键

矩阵键盘

代码:

7.中断系统

外部中断

通过引脚接收外部的高低电平,来触发中断

内部中断

通过内部的信号源触发中断(如定时中断)

                                                中断服务号

                         开关(TRx:定时/计数器启动位  1启动)

TCON:中断标志寄存器

SCON寄存器用于串口通讯

中断初始化函数:

   一个普通的函数,函数名任取,就是把中断的设置代码放到一个函数里

简单外部中断0的初始化函数:

void init(){

   IT0=1;  //设置为下降沿触发

   EX0=1;  //小开关闭合

   EA=1;  //大开关闭合

中断服务函数:

  void 函数名() interrupt 中断号

其中,函数名任意,中断号为图中对应中断服务号

注意,中断服务函数不需要被调用,会自动触发

外部中断时,

外部中断0的复合io口为P32,即按下独立按键s5,触发中断

外部中断1的复合io口为P33,即按下独立按键s4,触发中断

需要将跳帽接到独立键盘一边,而且复合的io口无法更改,即不能指定按键触发中断

代码:

8.定时器/计数器

原理:晶振产生波形信号,每个周期计数一次,从某个起点开始计数,直到记满产生溢出信号

16位计数器最大值为65535

晶振为12Mhz,选择12分频,进入计数器的脉冲就变为1Mhz,周期就为1μs

我们要设置计数起点,才能达到定时/计数的效果,设置的方法为:

设我们要定时x μs,则赋值:

TH0=(65536-x)/ 256     高8位

TL0=(65536-x) % 256         低8位

TMOD:模式寄存器

定时设置时,相关模式如下图内容所示

高4位-计数器1,低四位-计数器2

定时器编程思路:    (总思路:计数+中断)

  先配置TMOD模式寄存器,再根据要定时的时间计算计数初值并配置,最后配置计数器的中断功能

注意:使用16位计数器时,不具备自动重装功能,中断服务函数必须重置计数初值

代码:

9.IO口错乱问题解决

在同时综合运用多个模块时,比如要在led亮或灭时,蜂鸣器叫一下,代码如下:

上诉代码为用定时器实现led7每秒闪烁,并且在闪烁时,蜂鸣器叫一下,逻辑上没有问题。但在实际运行时,led的闪烁发生了错误。原因在于最后:

P0=0x00;//灭蜂鸣器

csh(4);//打开Y4

在打开Y4的瞬间,上面一句对P0的赋值影响了led的状态,所有的灯都亮了

即使在最后添加P0=P0 | 0x7e ,来熄灭中间的灯,两边的灯状态不变,但led7的闪烁依旧不正确

正确处理方法:现场保护法

定义一个变量a,在调用csh()之前,用a保存P0的值,当再次打开之前的Yx时,P0=a  即可

改进代码如下:

其他问题:无法关闭无关外设和数码管混乱

这段代码,实现的是在数码管上显示25.6这个数

而实际运行过程中,数码管其他5个数字也会亮,原因在于screen函数中,csh(6)前,P0有值,打开Y6通道的一瞬间就使得其他管段被点亮。所以,我们在前面给了赋值,P0=0x00;解决了数码管其他管不正常的问题。

但是,又出现了led被点亮,无法关闭的问题。原因在于,在main函数中,csh(4);P0=0xff;下一句代码就是screen中的第一句P0=0x00;点亮了led

解决办法:main函数初始化最后写csh(0);(要自己在csh函数里加上0的情况,即都给0)

类似地,如果蜂鸣器乱响,也是这样的情况

10.PWM

在高级单片机中,如32单片机,产生pwm波是一个固定的功能,而在51单片机中,只能用较为原始的方法来产生pwm(用定时器实现电平取反)。

pwm脉宽调式:即方波,有高电平,低电平,通过调节高电平的占空比,实现调节功率(直观地说,就是调节灯泡的亮度,电机的转速等)

编程思想步骤:

总的来说,就是在定时器的代码上进行修改

细说:

   先确定pwm波的频率,算出周期。如100Hz,周期就为0.01s,即10ms。

  再将10ms分成100份,即0.1ms,也是100μs,这个就是我们需要定时的时间。

  再定义一个变量 char k=0;

在中断服务函数中,(每定时一次)k++;

如果我们需要亮度为70%,则k在0~70时,点亮led,k在70~100时,熄灭led。k>100时,进行重置,即k=0并且点亮led

代码:

11.初始化函数的高级写法

代码如图所示

以Y4为例进行解释:

打开Y4,则  P27=1;P26=0;P25=0;

也可以直接对P2进行操作

P27 26 25 24 23 22 21 20

   1   0   0  0  0  0   0   0  →    0x80

即P2=0x80;

但是直接这样写,会影响到其他io口,即P24,P23,P22……所以,我们要直接对P2进行操作,还不影响P2其他的io口,就需要  &|  操作

&0 必为0   &1  不变

|1   必为1    |0  不变

P2=(P2&0x1f)   |  0x80;

括号中 (P2&0x1f)是固定的,作用是前三位清0,且不影响其他位

再 | 0x80  作用是将前3位变为100,且不影响其他位

其他的类似,规律:(P2&0x1f)不变,|后面的数刚好是Yx中x的两倍+0

12.MM模式(没用,不考)

——io扩展技术与存储器映射扩展

io模式:直接通过io口控制某些元件,前面我们一直用的都是io模式,比如点灯P00=0;

mm模式:通过存储地址控制

引入头文件“absacc.h”,j13跳帽接到mm模式

然后就可以通过XBYTE关键字进行操作了

具体:

XBYTE[0x8000]=0x00  就相当于

csh(4);P0=0x00;

(注:csh(4)是自己编写的初始化函数,作用是打开Y4)

XBYTE[0xa000]=0xff 就相当于

csh(5);P0=0xff;

其他类似

规律:地址为Yx中x的两倍+000

代码:

13.温度传感器DS18B20

使用温度传感器,需要用到官方提供的底层驱动程序,里面有一些进行相应操作的函数,我们调用里面的函数即可

注意:官方提供的驱动程序中,可能会挖坑,比如,他给的头文件.h文件中,缺少一些函数的声明,需要我们手动添加;

还有,文件夹中给了驱动程序的说明,里面有驱动运行的环境,如果一些参数和我们的环境不一致,我们就需要进行相应的修改。比如驱动环境为12T

而蓝桥杯板子的时钟是1T,我们就需要将官方提供的驱动.c文件中,函数里的延时时间都扩大到原来的12倍

代码思路步骤:

因为要显示出温度,所以要先写好数码管的代码

根据题目的要求,如保留几位小数,做一些修改,具体视具体情况而定

再写温度传感器的代码

这些操作,都是用官方提供的低层驱动程序实现的

ROM:64位空间,保存了设备的ID号,蓝桥杯板子上,单总线上只有DS18B20,所以不需要进行ID匹配,可以直接跳过ROM指令

延时700~900ms时需要同时扫描数码管

延时delay(1000)即可

代码:

数据处理:

注意:

  分辨率为0.0625,整数部分不需要×分辨率

小数部分需要×0.0625

需求:保留一位小数,并且在数码管上显示

代码:

解释:读取数据时,先读取的是低8位,后读取的是高8位。

int temp是一个32位的数,足够容纳16位数据

整合时,先temp=h8,左移8位,h8成为temp的高8位,低8位全为0,再 | l8 ,完成整合

因为我们需要显示在一位小数,在数码管显示中,我们需要将比如26.5这个数扩大为265,才方便写代码

所以,先判断高5位(符号位)是否都为0,是则为正数,再将temp右移4位(小数位);再把小数加回来,小数位只是l8的低4位

temp=(temp+(l8 &0x0f)*0.0625)*10

注意:整数部分不需要 * 分辨率

图中代码只是开括号把10乘了进去

数码管显示部分代码:

14.模块化设计-----头文件

当一个工程的代码很多,函数很多时,把所有代码放在main函数里,就会很混乱,不方便调试。

所以,我们需要自己编写头文件,把各个模块的代码分到不同的文件中,如数码管、按键、温度传感器等不同模块放在不同的.c文件中。

头文件编写步骤:

在工程中添加.c和.h文件,它们的名字必须一致

.c文件正常写,.h文件格式如下

宏定义名称是随意的,一般是文件名的大写,两个宏定义名称一致即可

随后,在#define和#endif之间放.c文件中函数的声明。

main中,要使用自己编写的头文件,写

#include“xxx.h”即可

在自己写的头文件中使用别的头文件也是一样的

15.实时时钟DS1302

Ds1302有两块寄存器,日历时钟寄存器(记录时间)和静态RAM存储器(用于用户自定义)

关注日历时钟寄存器即可

日历时钟寄存器即保存了年月日时分秒星期

这个表左边两列是重点,分别为:

读秒地址    写秒地址

读分地址    写分地址

读时地址    写时地址

……

0x8e是控制写入保护的地址

BCD码:直接将十进制数写为字面上的十六进制

比如,56直接写0x56,36直接写0x36

在读取数据时得到的也是BCD码,在数码管显示之前要进行转换,公式为:/16得到十位,%16得到个位;或者右移四位得到十位,前四位清零得到个位

控制字和寄存器的地址一样,细节可忽略

上面图片中的读操作地址,就是各读寄存器的地址,按顺序分别对应 秒分时日月 星期 年,写操作同理;

时间数组的内容和读写数组的顺序相对应,分别保存的是初始化的 秒分时日月 星期 年,后面时钟启动,读取新的时间后,数组里的内容会被改变

当然,你也可以修改数组的顺序为,年星期月日时分秒,要改三个数组的顺序都得改(保持一致)

编程操作:先把官方提供的驱动代码添加到工程

即,ds1302.h

代码:

解释:

一个写函数,一个读函数,格式基本固定

写函数就是利用循环把8个时间数据写入ds1302,当i=0时,写函数(秒寄存器地址,秒数据)

当i=1时,写函数(分寄存器地址,分数据)

……

读函数同理,但会修改时间数组的内容(除非另写一个数组)

数码管显示部分代码:

16.AD转换(电压)PCF8591

ad转换,a→模拟量,d→数字量

ad转换用到了iic(读作i方c),iic可以理解为通信协议,是传输数据用的,需要在工程中添加官方提供的驱动程序iic.

原理图:

pcf8591的iic通讯地址(电话号码)

  写0x90   读0x91

控制字定义

输出电压0x40  

读通道1(光敏)0x01     读通道3(电位器)0x03

代码思路步骤

输出模拟电压

翻译: 打电话→我要向pcf8591交代事情→等待应答(好的,你说)→我要让它输出电压→等待应答(好的,要输出几伏电压)→发送电压值→等待应答(好的)→挂电话

代码:

读取数字电压

翻译:打电话→我要向pcf8591交代事情→等待应答(好的,你说)→我要读取…通道的电压值→等待应答(好的,我现在让它反馈数据)→(给另一个人)打电话→我要读取pcf8591最新反馈的数据→等待应答(好的,那你记一下)→记录数据→数据已发生完毕→挂电话

代码:

数据处理和数码管显示

u不能是char类型,因为最大值超过了256

/51.0   和 /255.0*5  是一样的

最好不在读取和输出函数内处理数据,在外面处理比较好(因为要处理小数)

17.NE555定时器

事实上,NE555定时器是一个硬件设备,功能已经固定,是无法编程的,它的作用是产生某频率的方波信号,考试的题目就是测量它产生信号的频率(可以通过板子上的旋钮调节滑动变阻器的阻值,以调节频率)

而要测量频率,用的是T0和T1两个定时计数器,一个用来定时,另一个用来计数。所以,实际的考点是定时计数器

思路:

将j13的NAL和P34短接

                                (P34为T0的计数外部引脚)

    T0计数(8位自动重装计数模式,最大值255)

    T1定时(16位手动重装定时模式)

    此时,TMOD=0x16

T0的计数初值给255,每来一个脉冲,就会触发中断,中断服务函数中,让变量a++;

T1定时时间为1s(分段计时),当定时时间到时,

b=a;a=0;

b就是上一秒的频率,数码管显示b即可

代码:

18.AT24C02储存器

实际上,at24c02存储器的写数据和读数据的步骤和pcf8591电压的相关操作一致,只不过iic通讯地址不同

at24c02:

写0xa0,读0xa1

pcf8591:

写0x90,读0x91

数据写入

代码

数据读取

代码

函数调用

19.超声波

原理:用定时器计时超声波发射信号到接收信号的时间,这个时间/2×声速就是距离

步骤:

定义好TX和RX

1.发射信号:每延时10微秒,TX改变状态,循环8次

2.设置初值为0,开启定时器

3.等待接收到信号或定时器溢出(溢出了就是长时间没有收到信号,此时测量无效)

4.判断定时器溢出标志位,如果没溢出,则读取定时器的时间×0.017  就是距离(单位cm)

如果溢出,则清除溢出标志位,此次探测无效

注:定时器溢出时,TF1置1。

超声波模块收到信号时,Rx==0

代码:

超声波会有偏差

注:最佳测距代码:

发送信号时,循环8次。延迟时间10微秒。最后时间加156微秒

20.PCA定时器  (中断号为  7)

国赛中,同一项目里,超声波、频率、脉冲(pwm)、串口等内容通常一起出现,而它们需要都需要用到定时器。明显,两个定时器在国赛里是不够用的,所以,超声波测距,我们通常用PCA定时器(不需要中断)。另外,我们还可以再加一个T2定时器。这样我们就有了4个定时器。

Stc烧录软件不能生成PCA定时器的相关配置代码

都0x00即可

类似TMOD寄存器,PCA模式寄存器为CMOD

类似于TCON寄存器,PCA有CCON寄存器

这两个寄存器的配置记住即可

另外,CF 等同  TF  定时器中断使能

CR  等同  TR   定时器启动位

CH  等同  TH  定时器高8位

CL  等同   TL  定时器低8位

可以发现,各功能器一致,只是T改为了C

T2计时器:中断号为12

stc烧录软件能生成配置代码,相关原理也和T0定时器一致,只是命名不同

直接生成代码即可,简单

注意:如果要写中断服务函数,记得允许中断

即:IE2 |=0x04;

(不可位寻址,所以只能这么写)

21.定时器刷新数码管

之前用delay函数实现动态显示,需要在主循环中一直扫描。这种写法,对大延时的处理方式是,延时的时候扫描数码管,在大部分情况下都行得通,但在使用超声波模块时,出现了问题:

在等待接收信号或定时器溢出的循环中,如果在循环中扫描数码管,测量误差很大;不添加的话,数码管的显示又不稳定。

所以,我们只能用新的解决方法,那就是在定时器的中断函数中扫描数码管(2ms扫描一次)

代码:

smg.c中:

中断服务函数中

后面只需要调用smg_Set()就可以修改显示的内容

22.串口通讯

简单来说串口通讯就是两个机器之间进行数据传输,可以是单片机和电脑,单片机和手机,单片机和单片机。

这里我们学的是单片机和电脑之间进行数据传输

重要相关概念:

波特率:每秒传输的数据的位数

即波特率是传输的速度,双方都以这个标准进行数据的发生或接受,才能正常通讯

波特率就是一个数,这个数可以由定时器产生,定时器溢出一次,串口就传一次数据。如要产生9600的波特率,就让定时器每秒钟溢出9600次

(因为最多能做到1微秒溢出一次,而1秒=10^6微秒,所以理论上定时器能产生的最大波特率为10^6)

串口通讯的数据缓冲区:

缓冲寄存器SBUF,包括了发送寄存器和接收寄存器,它们在物理结构上是独立的,但软件地址是同一个地址99H

数据发送:把数据写入SBUF后,内核会自动发生数据,发送完成后,数据TI标志位会置1

故,数据发送的代码格式为:

unsigned char a=某个值; SBUF=a;

while(TI==0);  //等待数据发送完成

TI=0;  //手动标志位清零

数据接收:当接收一个完整的数据之后,RI标志位会置1。此时,直接读取SBUF的数据即可

(完整的数据:)

故,数据接收代码格式为:

unsigned char a;

if(RI==1){

   a=SBUF;

   RI=0;

注意:TI和RI标志位都需要软件手动清零

串口的中断号为4

当数据发生完成或接收完成时,都会进入中断,所以要进行对应的操作时,要判断是由数据发生完成产生的中断还是数据接收完成产生的中断。

接收数据(读取SBUF的数据),应该在串口的中断服务函数中实现。

发送数据随意。

串口模式寄存器SCON

8位数据,可变波特率,SCON=0x50

辅助寄存器AUXR(地址为0x8e)

用于选择哪个定时器作为波特率发生器

以及定时器的时钟频率

实际上,寄存器配置和波特率设置,都可以用stc烧录软件的波特率计算器进行生成,步骤就简单了很多

注意系统频率和我们烧录文件时所选频率必须保持一致。

打开串口时,串口号必须和USB一致

波特率也要和我们设置的波特率一致

小细节:

如果系统频率设为12Mhz,定时器不能用8位重装模式,(如9600的波特率)

虽然能生成,但实际有误差,串口通信会乱码

注意:生成时不会打开串口中断,所以需要我们添加代码:

ES=1;  //串口小开关

EA=1;  //大开关

加油写题吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值