蓝桥杯单片机总结(只拿了国三,不写了)
*以下是根据我个人国赛复习顺序而列 *
S1 串口
S1-1 串口初始化
串口1选择定时器2,原因后续再提。
直接用STC-ISP自动生成即可,仅需额外加两行代码。
再加上开启总中断和串口中断。
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xC7; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1; //串口中断
EA = 1; //总中断
}
好,串口的初始化已经完成了,为了方便串口发送,我们还需要重定向一下串口,原因可自行搜索。
char putchar(char c)
{
ES=0;
SBUF=c;
while(!TI);
TI=0;
ES=1;
return 0;
}
串口初始化,以及重定向后,就可以用printf进行输出了,大家死去的C语言记忆是不是开始攻击自己呢?
printf("A");printf("\r\n");
printf("123456\r\n");
printf("串口\r\n");
结果:
S1-2 串口发送与接收
S1-2-1 串口发送
注意!!!
使用printf时需要加上库函数stdio.h
数据定义:
unsigned char a=123;
char b=-123;
unsigned short c=12345;
short d=-12345;
unsigned int e=12345;
int f=-12345;
unsigned long g=99999999;
long h=-9999999;
float i=8888.6666;
发送:
printf("a=%bu\r\n",a);//实测,正数也可以用%bd
printf("b=%bd\r\n",b);
printf("c=%hu\r\n",c);//实测,正数也可以用%hd
printf("d=%hd\r\n",d);
printf("e=%hu\r\n",e);//实测,正数也可以用%hd
printf("f=%hd\r\n",f);
printf("g=%lu\r\n",g);//实测,正数也可以用%ld
printf("h=%ld\r\n",h);
printf("i=%.0f\r\n",i);
printf("i=%.1f\r\n",i);
printf("i=%.2f\r\n",i);
printf("i=%.3f\r\n",i);
printf("i=%.4f\r\n",i);
printf("i=%.5f\r\n",i);
结果:
在这篇帖子学到的
51单片机重定向printf函数 打印数值不正确问题
S1-2-2 串口接收
注意!!!
比较时需要加上库函数string.h
定义:
u8 urdat;
u8 xdata buf[10]; //接收到的数据
u8 index = 0; //buf数组索引
bit Uart_Ref = 0; //接收完成标志 1:接收完成
中断:
void Uart1_Isr(void) interrupt 4
{
if(RI)
{
RI = 0;
urdat = SBUF;
if(urdat == 'n')
{
Uart_Ref = 1;
buf[index] = 'n';
buf[index+1] = '\0';
index = 0;
}
else
{
buf[index++] = urdat; //接收的数据暂时存到数组里
}
}
}
执行:
if(Uart_Ref == 1) //接收完成
{
Uart_Ref = 0;
if(strcmp(buf,"Return") == 0)
{
printf("Noises:%hu\r\n",Freq);
}
}
这也是在C站上学来的,已经忘了原链接在哪
S2 频率
测频率使用定时器0,此时需要将开发版右侧P34与SIGNAL用跳线帽短接起来。
警告:测频率时会与矩阵按键发生冲突,使用时应当注意。
S2-1 初始化
定时器1初始化1ms:
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA=1;
}
定时器0初始化:
void Timer0_Init(void) //1毫秒@12.000MHz
{
TMOD |= 0x06; //设置定时器模式
TL0 = 0xff; //设置定时初始值
TH0 = 0xff; //设置定时初始值
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
数据定义:
u16 Freq=0,Count=0,t=0;
S2-2 定时器中断
定时器中断执行:
//定时器1:
void Timer1_Isr(void) interrupt 3
{
t++;
if(t>=1000)
{
Freq=Count;
Count=0;
t=0;
}
}
//定时器0:
void Timer0_Isr(void) interrupt 1
{
Count++;
}
S2-3 结果
输出:
while(1)
{
Delay1000ms();
printf("Freq=%hu",Freq);
}
结果:
S3 超声波
S3-1 超声波初始化
初始化:
原理可自行百度
void Delay13us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 36;
while (--i);
}
void Send_Sonic()
{
u8 i = 8;
while(i--)
{
Sonic_TX=1;
Delay13us();
Sonic_TX=0;
Delay13us();
}
}
u16 GetDist()
{
u16 dist;
Send_Sonic();
CR=1;
while((Sonic_RX)&&(!CF));
CR=0;
if(CF==1)
{
CF=0;
return 999;
}
else
{
dist=CH*256+CL;
dist*=0.017;
}
CH=0;
CL=0;
return dist;
}
直接在main函数中调用即可
GetDist()返回值是单位为cm的数
Delay13us()中的i=36可微调
S4 温度ds18b20
话不多说,直接上代码
unsigned long GetTemp()
{
unsigned long Dat;
u8 high,low;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
Dat=0x0f&high;
Dat<<=8;
Dat|=low;
Dat*=625;
return Dat;
}
返回值很长
DigBuf[6]=TEMP_Value%1000000/100000;
DigBuf[7]=TEMP_Value%100000/10000;
显示个位和百位