stc15笔记
为了蓝桥杯单片机开发赛道。由于各种原因,一直没赶上培训,所以就自学。自学也不错,一两个小时下来的效率比听讲要高很多,还能集百家之长,还能随便写点东西出来。
实话说,我现在手上这些的芯片,其速度大都超越了上个世纪八十年代的所有芯片——而且存储空间很大,封装体积很小,随便就能吊打当时的任何超级计算机——如果有。
头文件
- STC15F2K60S2.h
- intrins.h
下面是基础篇。
坑 & 注意
int的位数
STC15的int是16位的!!!
想要用32位还是得用long
2023年了,你甚至还可以遇到16位的上古int
建议手动typedef
出uint16_t
之类的类型以方便使用。
P25、P26、P27
要注意这三个寄存器位的写入顺序,推荐的顺序是P27->P26->P25,这样似乎不容易误操作。
UART与时钟
UART会占用一个时钟,要使用UART调试的话你就只能用一个时钟了。
引脚
STC15的输出电平都是弱上拉,所以在矩阵按键里应该扫描低电平作为按键的标志。
点灯与简单按键
懒得截原理图了,直接上网找了一篇:
抛个链接:蓝桥杯STC15单片机复习——IO口的使用,代码是我自己写的
1 |
|
矩阵按键
懒得截原理图了,直接上网找了一篇:
抛个链接:蓝桥杯STC15单片机复习——矩阵按键使用,代码是我自己写的
我的定义:以此图左上角按键为1,向右递增,然后按排数排列。也就是:
1 2 3 4
5 6 7 8
…
原理也很简单,懒得复述。
1 | // 如果无按键,返回0x00,否则返回按键编号(1-16) |
可以加个消抖之类的。
数码管显示
也懒得解释。
抛个链接:蓝桥杯STC15单片机复习——数码管的使用,部分代码是改写的
1 |
|
至于while(1)调用NumberTubes_ShowNum()
的部分这里就不写了。建议到时候用时钟。
中断与计数器与时钟
摇滚与孤独与蓝色星球
外部中断
外部中断用得比较少
如上图所示,STC15的单片机的外部中断分别位于P32、P33(EX0、EX1),其中,外部中断0的中断号为0,外部中断1的中断号为2.
直接interrupt n
就行。
完。
时钟与计数器
STC15上带有一个NE555,就让它输出的波形到计数器上去吧。
在定时器1的中断服务函数中,将采集到的脉冲数*2并显示出来,即可得到频率。
经过引文作者的测试,输出的频率确实为采集到的脉冲数的两倍。
Timer0
对应中断1,Timer1
对应中断3.timer初始化代码能直接用stc-isp获取。
1 | void Timer0Init(void) //5毫秒@11.0592MHz 5ms |
UART
直接代码。
UartInit()代码能直接用stc-isp获取。
1 |
|
温度检测
如上图数据手册所示,DS18B20在进行温度转换以后,得到的是16位的数据,即高八位high,低八位low。其中,高八位的前五位代表符号位,当温度为正值时,这五位都为0,反之都为1;高八位的后三位与低八位的前四位共同组成了整数位。
因此,在只显示整数时,我们只需要将高八位左移四位,随后或上低八位的前四位,即可得到整数的温度值;
对于小数部分,我们只需要定义一个十六位数据,保留高八位的的后四位(&0x0f),随后拼上低八位并乘以0.0625(最小精度),即可得到小数部分的数值。
1 | uint8_t DS18B20_Get() |
DS1302
它是个时钟芯片。DS1302有什么用呢?它就相当于,当你给电脑关机后,你的电脑仍然能够进行计时,当你再次开机时,你的电脑能够不联网地准确获取当前时间。
DS1302的作用是“掉电”存储功能,当你关闭开关,它将继续工作——除非你拔掉了USB,或者是进行物理破坏(误)。
下面的代码就是链接里的改写。time_dat
是直接读取到的时间,需要注意进制上的写法与实际显示上的写法的转换。(如从0x48->48)
1 | void DS1302_Write(unsigned char *time_dat) |
我一开始没明白这句话是什么意思,直到我再看了一眼寄存器定义,我发现它和汇编中断获取当前时间的数据格式几乎一致。于是秒懂:
简单解释一下:假定此时秒数为58,那么它在寄存器里会直接给你写成0x58,而不是58所对应的0x3A,直接读取和使用会产生错误——你读取到的是0x58,也就是十进制下的88。
具体地,以获取Seconds
为例:
在DS1302的寄存器中,
- 高四位存储的数值=十位上的数字
- 低四位存储的数值=个位上的数字
秒的取值范围是00~59,在读取时,我们读取寄存器的值,将高四位的数值搁在十位上,将低四位的数值搁在个位上,于是有
1 | uint8_t seconds_in_register = 0x58; |
上述过程写出了详细步骤,具体代码可以化简,反过来就是写入的转化过程。
DA/AD
抛个链接:蓝桥杯电子类单片机组模块——DAC
另外:见下面的PCF部分。
在蓝桥杯电子类单片机组历年的省赛以及国赛中,DAC模块常常被考察到。而组委会为减轻考生负担,提前给出了关于DAC模块的代码,剩下的便需要我们自己去编写(以第十届为例)。
可能……考试时我需要补全一些“第三方库”中的不完整代码?
在模块C文件里:
1 | void write_dac(unsigned char add) |
在Header文件里
1 | void write_adc(unsigned char add); |
然后就可以正常使用了。
在main里可以直接运用ADC模块。
AT24C02
AT24C02是一种能掉电(真正意义上的)存储的芯片,存储介质为EEPROM,I2C通信。
关于I2C通信如何实现,自己搞一块OLED0.96inc的屏幕,然后对着其他人的轮子敲一遍驱动程序就能完全理解。
抛个链接:AT24C02详解(蓝桥杯单片机模块(IIC总线))。比赛方提供IIC的文件。因为STC15开发板采用了单总线的设计,所以直接拿过来用就可以了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//写函数(2byte)
void v_AtW(uint8_t addr, uint16_t dat)
{
IIC_Start();
IIC_SendByte(SlaveAddrW);
IIC_WaitAck();
IIC_SendByte(addr*2);
IIC_WaitAck();
IIC_SendByte(dat >> 8);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//读函数(2byte)
uint16_t u_AtR(uint8_t addr)
{
uint16_t _data;
IIC_Start();
IIC_SendByte(SlaveAddrW);
IIC_WaitAck();
IIC_SendByte(addr*2);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(SlaveAddrR);
IIC_WaitAck();
_data = IIC_RecByte();
IIC_SendAck(0);
_data = _data << 8 | IIC_RecByte();
IIC_Stop();
return _data;
}
只要不发送停止信号,EEPROM就会顺着地址一直读/写下去。这里就是利用了这个特性读取和写入了2byte字节。
关于从机地址、读写规则请阅读上面的文章。
PCF8591
抛个链接:PCF8591详解(蓝桥杯单片机模块(IIC总线)),过。
赛题
十二届赛题
竞赛板配置要求
- 将 IAP15F2K61S2 单片机内部振荡器频率设定为 12MHz。
- 键盘工作模式跳线 J5 配置为 KBD 键盘模式。
- 扩展方式跳线 J13 配置为 IO 模式。
- 请注意:选手需严格按照以上要求配置竞赛板,编写和调试程序,不符合以上配置要求的作品将被评为零分或者被酌情扣分。
功能概述
- 通过获取 DS18B20 温度传感器的温度数据,完成温度测量功能。
- 通过 PCF8591 AD/DA 芯片完成 DAC 输出功能。
- 通过数码管完成题目要求的数据显示功能。
- 通过按键完成题目要求的显示界面切换和设置功能。
- 通过 LED 指示灯完成题目要求的指示功能。
性能要求
- 温度数据刷新时间:≤1 秒。
- DAC 输出电压刷新时间:≤0.5 秒。
- 按键动作响应时间:≤0.2 秒。
显示功能
- 温度显示界面
温度数据界面如图 2 所示,显示内容包括标识符 C 和温度数据,温度数据保留小数点后 2 位有效数字,单位为摄氏度。
C | 8 | 8 | 8 | 2 | 4. | 2 | 5 |
---|---|---|---|---|---|---|---|
标识 | 熄灭 | 熄灭 | 熄灭 | 温度:24.25℃ | 温度:24.25℃ | 温度:24.25℃ | 温度:24.25℃ |
- 参数设置界面
参数设置界面如图 3 所示,显示内容包括标识符 P 和温度参数,温度参数为整数,单位为摄氏度。
C | 8 | 8 | 8 | 8 | 8 | 2 | 5 |
---|---|---|---|---|---|---|---|
标识 | 熄灭 | 熄灭 | 熄灭 | 熄灭 | 熄灭 | 参数:25℃ | 参数:25℃ |
- DAC 输出界面
DAC 输出界面如图 4 所示,显示内容包括标识符 A 和当前 DAC 输出的电压值,电压数据保留小数点后 2 位有效数字。
C | 8 | 8 | 8 | 8 | 3. | 2 | 5 |
---|---|---|---|---|---|---|---|
标识 | 熄灭 | 熄灭 | 熄灭 | 熄灭 | VDAC = 3.25V | VDAC = 3.25V | 温VDAC = 3.25V |
按键功能
功能说明
- S4:定义为“界面”按键,按下 S4 按键,切换温度显示界面、参数设置界面和 DAC 输出界面,按键 S4 切换模式如图 5 所示:
S4
- S8:定义为“减”按键
在参数界面下按下 S8 按键,温度参数减 1。 - S9:定义为“加”按键
在参数界面下按下 S9 按键,温度参数加 1。 - S5:定义为“模式”切换按键。
模式 1:DAC 输出电压与温度相关。
通过 DS18B20 采集到的实时温度小于温度参数时,DAC 输出 0V,否则,DAC 输出 5V。
模式 2:DAC 按照图 7 给出的关系输出电压。
其它要求
- 按键应做好消抖处理,避免出现一次按键动作导致功能多次触发等问题。
- 按键动作不影响数码管显示和数据采集过程。
- S8、S9 按键仅在参数设置界面有效。
- 设定的温度参数在退出参数设置界面时生效。
LED 指示灯功能
- 当前处于 模式 1 状态,指示灯 L1 点亮,否则熄灭。
- 当前处于温度显示界面,指示灯 L2 点亮,否则熄灭。
- 当前处于参数设置界面,指示灯 L3 点亮,否则熄灭。
- 当前处于 DAC 输出界面,指示灯 L4 点亮,否则熄灭。
初始状态说明
请严格按照以下要求设计作品的上电初始状态。
- 处于温度显示界面。
- 处于模式 1。
- 温度参数为 25℃。
代码
一下是我实现的一个思路。
1 |
|
除此之外,还有在文件中补全的部分代码为:
onewire.h
删除了 char rd_remperature(void);
1 | float rd_temperature(void); |
onewire.c
1 | void start_convert_ds18b20(void) |
十一届赛题
题目
见这个:https://blog.csdn.net/qq_53960242/article/details/123997096
代码
1 |
|
十届赛题
题目
略
代码
1 |
|
大吉大利,四月吃鸡
更新说明
- 2023.6.16:自定义标签适应新的博客主题Icarus。