文章目录
- 前言
- 总结了一些蓝桥杯单片机基础的模块。教程可参考小蜜蜂老师的单片机课程。下面是老师课程的链接。 [【历届蓝桥杯单片机省赛真题考点归纳】](https://bbs.21ic.com/icview-2480602-1-1.html)
- 一、基础模块
- 1.基本模板
- 2.外部中断0
- 3.定时器0
- 4.串口(以定时器1为时钟源)
- 5.温度传感器
- 6.实时时钟(秒分时日月周年,BCD码计数)
- 7.ADC
- 8.EEPROM(设备地址 0xA0)
- 9.矩阵按键
- 10.超声波
- 11.频率测量(555定时器Rb3调节频率)
- 12.模拟PWM(选取一个PWM周期)
- 总结
前言
总结了一些蓝桥杯单片机基础的模块。教程可参考小蜜蜂老师的单片机课程。下面是老师课程的链接。
【历届蓝桥杯单片机省赛真题考点归纳】
一、基础模块
1.基本模板
#include "reg52.h"
#include "iic.h"
#include "onewire.h"//关于延时的函数里的参数乘以10
#include "intrins.h"//内含nop,超声波用到
#include "ds1302.h"//时间数据采用BCD码
//iic.h里的 _IIC_H ==> __IIC_H
//onewire 涉及延时的参数*10,函数未在头文件声明
typedef unsigned char uint8;
typedef unsigned int uint32;
#define LED_Channel 4
#define BEEP_DELAY_Channel 5
#define COM_Channel 6
#define SMG_Channel 7
sfr P4 = 0xc0;
sfr AUXR = 0x8e;
//超声波接口
sbit TX = P1^0;
sbit RT = P1^1;
//数码管编码
uint8 code TAB[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
//带小数点
uint8 code Dot_TAB[16]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e} ;
//矩阵按键接口 J5:12
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;
//独立按键 J5:23
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
//自定义变量
uint8 node //显示界面编号
uint32 temp//读取温度
uint8 cnt_f//频率计数
void Delay(uint32 ms)
{
uint32 x,y;
for(x=0;x<ms;x++)
for(y=846;y>0;y--){}
}
void InitHC138(uint8 Channel)
{
switch(Channel)
{
case 4:P2 = (P2 & 0x1f) | 0x80;break;
case 5:P2 = (P2 & 0x1f) | 0xa0;break;
case 6:P2 = (P2 & 0x1f) | 0xc0;break;
case 7:P2 = (P2 & 0x1f) | 0xe0;break;
default:P2 &= 0x1f;
}
}
void Init_System(void)
{
InitHC138(BEEP_DELAY_Channel);
P0 = 0x00;
InitHC138(LED_Channel);
P0 = 0xff;
InitHC138(0);
}
void Display_Bit(uint8 pos,uint8 date)
{
InitHC138(COM_Channel);
P0 = 0x01<<pos;
InitHC138(SMG_Channel);
P0 = date;
InitHC138(0);
}
void Display_All(uint8 date)
{
InitHC138(COM_Channel);
P0 = 0xff;
InitHC138(SMG_Channel);
P0 = date;
InitHC138(0);
}
void Dislpay(uint8 node)//第十二届省赛数码管显示代码
{
switch(node)
{
case 0:
Display_Bit(0,TAB[12]),Delay(1);
Display_Bit(1,0xff),Delay(1);
Display_Bit(2,0xff),Delay(1);
Display_Bit(3,0xff),Delay(1);
Display_Bit(4,TAB[temp/1000]),Delay(1);
Display_Bit(5,Dot_TAB[(temp%1000)/100]),Delay(1);
Display_Bit(6,TAB[(temp%100)/10]),Delay(1);
Display_Bit(7,TAB[temp%10]),Delay(1);
Display_All(0xff);
break;
case 1:
Display_Bit(0,TAB[18]),Delay(1);
Display_Bit(1,0xff),Delay(1);
Display_Bit(2,0xff),Delay(1);
Display_Bit(3,0xff),Delay(1);
Display_Bit(4,0xff),Delay(1);
Display_Bit(5,0xff),Delay(1);
Display_Bit(6,TAB[default_temp/10]),Delay(1);
Display_Bit(7,TAB[default_temp%10]),Delay(1);
Display_All(0xff);
break;
case 2:
if(mode == 0)
{
Display_Bit(0,TAB[10]),Delay(1);
Display_Bit(1,0xff),Delay(1);
Display_Bit(2,0xff),Delay(1);
Display_Bit(3,0xff),Delay(1);
Display_Bit(4,0xff),Delay(1);
Display_Bit(5,Dot_TAB[Vdac]),Delay(1);
Display_Bit(6,TAB[0]),Delay(1);
Display_Bit(7,TAB[0]),Delay(1);
Display_All(0xff);
}
else
{
Display_Bit(0,TAB[10]),Delay(1);
Display_Bit(1,0xff),Delay(1);
Display_Bit(2,0xff),Delay(1);
Display_Bit(3,0xff),Delay(1);
Display_Bit(4,0xff),Delay(1);
Display_Bit(5,Dot_TAB[Vdac/100]),Delay(1);
Display_Bit(6,TAB[(Vdac%100)/10]),Delay(1);
Display_Bit(7,TAB[Vdac%10]),Delay(1);
Display_All(0xff);
}
break;
default:Display_All(0xff);break;
}
}
void SMG_Delay(uint32 t)
{
while(t--)
{
Dislpay(node);
}
}
- 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
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
2.外部中断0
//P32 INT0 P33 INT1
//J5 23:独立按键
void INT0_Init()
{
IT0 = 1;//下降沿
EX0 = 1;
EA = 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
3.定时器0
void Timer0Init(void) // 10 毫秒 @11.0592MHz
{
AUXR &= 0x7F;// 定时器时钟 12T 模式 FOSC/12 65.536ms
TMOD &= 0xF0;// 设置定时器模式
TL0 = 0x00;// 设置定时初值
TH0 = 0xDC;// 设置定时初值
TF0 = 0;// 清除 TF0 标志
TR0 = 1;// 定时器 0 开始计时
ET0 = 1;
EA = 1;
}
void Time0_Hander() interrupt 1
{
//可将读取温度,adc采集的标志放入中断,提高效率
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
4.串口(以定时器1为时钟源)
void UartInit(void)//9600bps@11.0592MHz
{
SCON = 0x50;// 8位数据,可变波特率
AUXR |= 0x40;// 定时器1时钟为Fosc,即1T
AUXR &= 0xFE;// 串口1选择定时器1为波特率发生器
TMOD &= 0x0F;// 设定定时器1为16位自动重装方式
TL1 = 0xE0;// 设定定时初值
TH1 = 0xFE;// 设定定时初值
ET1 = 0;// 禁止定时器1中断
TR1 = 1;// 启动定时器1
ES = 1; // 允许串口中断
EA = 1; // 开启总中断
}
void Send_Byte(uint8 date)
{
SBUF = date;
while(TI == 0){}
TI = 0;
}
void Uart_Hander(void) interrupt 4
{
if(RI == 1)
{
RI = 0;
getdate = SBUF;
Send_Byte(getdate);
}
}
- 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
5.温度传感器
初始化 0xcc 0x44 延时
初始化 0xcc 0xbe 读取
第一种方式
//初始化,跳过rom,操作
//前5位是符号位,后4位是小数位,小数存放在LSB(低位先读),//0.0625*10
void Read_Temp(void)
{
uint8 LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc); //跳过ROM指令
Write_DS18B20(0x44);//开始温度转换
SMG_Delay(50);
//可用 Delay_OneWire(200); // 延时一段时间
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM指令
Write_DS18B20(0xbe);//读取高速暂存器
LSB =Read_DS18B20(); //读取第一个字节
MSB =Read_DS18B20();//读取第二字节
temp = (MSB<<8)|LSB;
//包含小数 ,如果不包含小数,直接将temp右移4位即可
if((temp & 0xf800)== 0x0000) //判断高五位符号位是否为0 ,即是否为证书
{
temp = temp>>4;
temp = temp * 10;
temp = temp + (LSB & 0x0f)*0.625 ;//0.0625*10
}
}
- 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
第二种方式
uint32 Read_Temp(void)
{
uint8 LSB,MSB;
uint32 temp;
init_ds18b20();
Write_DS18B20(0xcc); //跳过ROM指令
Write_DS18B20(0x44);//开始温度转换
//SMG_Delay(50);
Delay_OneWire(200); // 延时一段时间
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM指令
Write_DS18B20(0xbe);//读取高速暂存器
LSB =Read_DS18B20(); //读取第一个字节
MSB =Read_DS18B20();//读取第二字节
temp= ((MSB&0x0f)<<8)| LSB;
return temp;
}
temperature = Read_Temp()*0.0625;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
6.实时时钟(秒分时日月周年,BCD码计数)
允许写0x8E,0x00
操作
禁止写0x8E,0x80
//定义DS1302写操作的日历时钟存储器地址
uint8 Write_DS1302_addr[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//定义DS1302读操作的日历时钟存储器地址
uint8 Read_DS1302_addr[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
uint8 time[7] = {0x30,0x12,0x08,0x10,0x01,0x03,0x21}//21年3周1月10日8点12分30秒
//十位数 time[i]/16 个位数 time[i]%16
void DS1302_Init(void)
{
uint8 n;
Write_Ds1302_Byte(0x8E,0x00);//允许写
for(n=0;n<7;n++)
{
Write_Ds1302_Byte(Write_DS1302_addr[n],Timer[n]);
}
Write_Ds1302_Byte(0x8E,0x80);//禁止写
}
void Read_DS1302_Time(void)
{
uint8 n;
for(n=0;n<7;n++)
{
Timer[n] = Read_Ds1302_Byte ( Read_DS1302_addr[n]);
}
}
- 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
7.ADC
PCF8951 地址 0x90
可调电阻Rb2 0x03
LM32 0x02(差分输入)
光敏电阻 0x01
外部引脚 0x00
uint8 Read_ADC(uint8 ch) //可调电阻rb2
{
uint8 date;
IIC_Start();//IIC总线起始信号
IIC_SendByte(0x90); //PCF8591的写地址 读地址为0x91
IIC_WaitAck();//等待从机应答
IIC_SendByte(ch);//写入PCF8591的控制字节
IIC_WaitAck(); //等待从机应答
IIC_Start();//IIC总线起始信号
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck();//等待从机应答
date= IIC_RecByte();//读取目标数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop();//IIC总线停止信号
return date
}
void DAC(uint8 date)// 输入值需要转换
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
- 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
8.EEPROM(设备地址 0xA0)
读取一个字节要Delay(10);
void WriteByte(uint8 addr, uint8 date)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
uint8 ReadByte(uint8 addr)
{
uint8 date;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa0 | 0x01);
IIC_WaitAck();
date = IIC_RecByte();
IIC_Ack(1);
IIC_Stop();
return date;
}
- 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
9.矩阵按键
void Key_Scan()
{
R1=0,R2=1,R3=1,R4=1;
C1=1,C2=1,C3=1,C4=1;
if(C1==0)
{
Delay(10);
if(C1==0)
{
while(C1==0);
}
}
if(C2==0)
{
Delay(10);
if(C2==0)
{
while(C2==0);
}
}
if(C3==0)
{
Delay(10);
if(C3==0)
{
while(C3==0);
}
}
if(C4==0)
{
Delay(10);
if(C4==0)
{
while(C4==0);
}
}
R1=1,R2=0,R3=1,R4=1;
C1=1,C2=1,C3=1,C4=1;
if(C1==0)
{
Delay(10);
if(C1==0)
{
while(C1==0);
}
}
if(C2==0)
{
Delay(10);
if(C2==0)
{
while(C2==0);
}
}
if(C3==0)
{
Delay(10);
if(C3==0)
{
while(C3==0);
}
}
if(C4==0)
{
Delay(10);
if(C4==0)
{
while(C4==0);
}
}
R1=1,R2=1,R3=0,R4=1;
C1=1,C2=1,C3=1,C4=1;
if(C1==0)
{
Delay(10);
if(C1==0)
{
while(C1==0);
}
}
if(C2==0)
{
Delay(10);
if(C2==0)
{
while(C2==0);
}
}
if(C3==0)
{
Delay(10);
if(C3==0)
{
while(C3==0);
}
}
if(C4==0)
{
Delay(10);
if(C4==0)
{
while(C4==0);
}
}
R1=1,R2=1,R3=1,R4=0;
C1=1,C2=1,C3=1,C4=1;
if(C1==0)
{
Delay(10);
if(C1==0)
{
while(C1==0);
}
}
if(C2==0)
{
Delay(10);
if(C2==0)
{
while(C2==0);
}
}
if(C3==0)
{
Delay(10);
if(C3==0)
{
while(C3==0);
}
}
if(C4==0)
{
Delay(10);
if(C4==0)
{
while(C4==0);
}
}
}
- 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
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
10.超声波
void Timer1Init(void)//10微秒@11.0592MHz
{
TMOD &= 0x0F;//设置定时器模式
//AUXR |= 0x40;//定时器时钟1T模式
//TL1 = 0x91;//设置定时初始值
//TH1 = 0xFF;//设置定时初始值
//TF1 = 0;//清除TF1标志
//TR1 = 1;//定时器1开始计时
}
void Delay12us()//@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void Send_Wave(void)
{
uint8 i=0;
for(i=0;i<8;i++)
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
void Measure_Distance(void)
{
AUXR |= 0x40;//定时器时钟1T模式
TL1 = 0x00;//设置定时初始值
TH1 = 0x00;//设置定时初始值
TF1 = 0;//清除TF1标志
Send_Wave();
TR1 = 1;//定时器1开始计时
while((RT==1)&&(TF1==0));
TR1 = 0;
if(TF1 == 1)
{
distance = 999;
TF1 = 0;
}
else
{
time = TH1;
time = (time<<8)|TL1;
distance = time*0.017/11.0592//(f);
}
}
- 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
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
11.频率测量(555定时器Rb3调节频率)
void Init_Timer01(void)
{
TMOD = 0x16;
TH0 = 0xff;
TL0 = 0xff;
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
TR0 = 1;
ET0 = 1;
TR1 = 1;
ET1 = 1;
EA = 1;
}
void Timer0_Service() interrupt 1
{
cnt_f ++;
}
void Timer1_Service() interrupt 3
{
TH1 = (65536 - 50000)/256;
TL1 = (65536 - 50000)%256;
cnt_t ++;
if(cnt_t == 20)
{
cnt_t = 0;
dat = cnt_f;
cnt_f = 0;
}
}
void Init_TF0(void)
{
TMOD = 0x01;
//0.1ms
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
ET0 = 1;
EA = 1;
TR0 = 0;
}
void TF0_Hander(void) interrupt 1
{
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
cnt++;
if(cnt <= cmp)
{
InitHC138(LED_Channel);
P0 = 0xfe;
}
else if(cnt <100)
{
InitHC138(LED_Channel);
P0 = 0xff;
}
else
{
cnt = 0;
InitHC138(LED_Channel);
P0 = 0xff;
}
}
- 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
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
12.模拟PWM(选取一个PWM周期)
void Init_TF0(void)
{
TMOD = 0x01;
//0.1ms
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
ET0 = 1;
EA = 1;
TR0 = 0;
}
void TF0_Hander(void) interrupt 1
{
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
cnt++;
if(cnt <= cmp)
{
InitHC138(LED_Channel);
P0 = 0xfe;
}
else if(cnt <100)
{
InitHC138(LED_Channel);
P0 = 0xff;
}
else
{
cnt = 0;
InitHC138(LED_Channel);
P0 = 0xff;
}
}
- 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
总结
先这样吧,有错误再改,后续看看能不能把历届省赛的代码贴出来。
文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览42750 人正在系统学习中