蓝桥杯单片机模板(自用)——基于柳离风模板
文章目录
一、工程结构
二、USER文件夹
main.c
存放main函数,按键任务,采集任务,显示任务,主逻辑等。
main.c
#include <STC15F2K60S2.H>
#include "sys.h"
#include "display.h"
#include "key.h"
#include "timer.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#include "uart.h"
#include "ultrasound.h"
/* 变量区 */
uchar SMG[8] = {20,20,20,20,20,20,20,20}; //数码管显示
uchar dot[8] = {0,0,0,0,0,0,0,0}; //小数点显示
uchar LED[8] = {0,0,0,0,0,0,0,0}; //led显示
uint temperature; //温度变量
uchar state_display = 5; //显示状态
bit state_led;
/* 函数区 */
//显示任务
void display_task(void)
{
/*LED任务*/
LED[0] = state_led;//放在延迟判断前,这样闪烁间隔才正常
LED[1] = 1;
LED[2] = 0;
LED[3] = 1;
LED[4] = 0;
LED[5] = 1;
LED[6] = 0;
LED[7] = 1;
if(display_dly<100)return;
display_dly = 0;
/*数码管任务*/
switch(state_display)
{
case 0: /*频率显示*/
SMG[0] = 15;
SMG[1] = 20;
SMG[2] = 20;
SMG[3] = (fre<10000) ? 20:fre/10000;
SMG[4] = (fre<1000) ? 20:fre/1000%10;
SMG[5] = (fre<100) ? 20:fre/100%10;
SMG[6] = (fre<10) ? 20:fre/10%10;
SMG[7] = fre%10;
break;
}
}
//采集任务
void collect_task(void)
{
if(collect_dly<300)return;
collect_dly = 0;
temperature = ds18b20_read(0);
// printf("温度是:%d°C\r\n",(uint)temperature);
}
//按键处理任务
void key_task(void)
{
uchar key_num;
if(key_dly<10)return;
key_dly = 0;
// key_num = key_scan1();
key_num = key_scan2();
switch (key_num)
{
/* 独立按键 */
// case 4:
// break;
// case 5:
// break;
// case 6: state_relay = ~state_relay;
// break;
// case 7: state_beep = ~state_beep;
// break;
/* 矩阵键盘 */
case 4:
break;
case 5:
break;
case 8: state_relay = ~state_relay;
break;
case 9: state_led = ~state_led;
break;
}
}
void main(void)
{
sys_init(); //系统初始化-关闭蜂鸣器继电器
Timer0_Init(); //定时器0-计数模式初始化
Timer1_Init(); //定时器1-1ms中断任务调度初始化
// Uart1_Init(); //串口1初始化9600波特率,与矩阵键盘几个引脚冲突
ds1302_write(); //ds1302时钟初始化-写入时间
ds18b20_read(0); //ds18b20初始化-上电默认85度,先读一下,延时750ms,再读一下
// delay_ms(750);
// temperature = ds18b20_read(0);
AT24C02_write(1,123); //EEPROM初始化-写入值
EA = 1; //打开总中断
while(1)
{
key_task();
collect_task();
display_task();
}
}
三、BSP文件夹
1、sys
存放系统初始化函数和公用函数、定义等,包括hc573锁存器操作、上电关闭蜂鸣器继电器函数、延时函数、顶层头文件和宏定义等。
sys.c
#include "sys.h"
/**
* @brief 实现led,继电器蜂鸣器,数码管通道的选择
*
* @param channel 4:led,5:继电器蜂鸣器,6:位选,7:段选
*/
void hc573(uchar 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;
}
P2 = P2 & 0x1f;
}
/**
* @brief 系统初始化,关闭led、蜂鸣器继电器,交换位置解决数码管上电闪烁的问题
*
*/
void sys_init(void)
{
P0 = 0xff;
hc573(4);
P0 = 0x00;
hc573(5);
}
/**
* @brief ms级延时
*
* @param xms 延时ms数
*/
void delay_ms(uint xms) //@12.000MHz
{
unsigned char data i, j;
while(xms--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
/**
* @brief us级延时
*
* @param xus 延时us数
*/
void delay_us(uint xus) //@12.000MHz
{
while(xus--)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
sys.h
#ifndef __SYS_H
#define __SYS_H
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "stdio.h"
#define uchar unsigned char
#define uint unsigned int
void hc573(uchar channel);
void sys_init(void);
void delay_ms(uint xms);
void delay_us(uint xus);
#endif
2、display
存放显示驱动函数,包括LED,数码管,继电器,蜂鸣器等外设的控制。
display.c
#include "display.h"
uchar uln2003 = 0x00;//蜂鸣器继电器对应锁存器当前状态
// 共阳数码管段码表
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A10
0x83, //b11
0xc6, //C12
0xa1, //d13
0x86, //E14
0x8e, //F15
0x89, //H16
0x8c, //P17
0xc7, //L18
0xbf, //-19
0xff //灭20
};
/**
* @brief led显示
*
* @param LED led数组首地址
* @param pos 数组索引
*/
void led(uchar * LED,uchar pos)
{
static uchar temp = 0xff;
if(LED[pos])
temp &= ~(0x01 << pos);
else
temp |= 0x01 << pos;
P0 = temp;
hc573(4);
}
/**
* @brief 数码管显示
*
* @param SMG 数码管数组首地址
* @param dot 小数点数组首地址
* @param pos 数组索引
*/
void smg(uchar * SMG,uchar * dot,uchar pos)
{
P0 = 0xff; //消隐
hc573(7);
P0 = 0x01 << pos; //位选
hc573(6);
if(dot[pos]) //段选
P0 = Seg_Table[SMG[pos]] & 0x7f;
else
P0 = Seg_Table[SMG[pos]];
hc573(7);
}
/**
* @brief 继电器控制
*
* @param state_relay 0关1开
*/
void relay(uchar state_relay)
{
if(state_relay)
uln2003 |= 0x10;
else
uln2003 &= ~0x10;
P0 = uln2003;
hc573(5);
}
/**
* @brief 蜂鸣器控制
*
* @param state_beep 0关1开
*/
void beep(uchar state_beep)
{
if(state_beep)
uln2003 |= 0x40;
else
uln2003 &= ~0x40;
P0 = uln2003;
hc573(5);
}
display.h
#ifndef __DISPLAY_H
#define __DISPLAY_H
#include "sys.h"
void led(uchar * LED,uchar pos);
void smg(uchar * temp,uchar * dot,uchar pos);
void relay(uchar state_relay);
void beep(uchar state_beep);
#endif
3、key
存放按键扫描函数,包括独立按键和矩阵键盘,这里返回值为按键在开发板上的元件位号,使用时注意和串口,NE555冲突的引脚。
key.c
#include "key.h"
/**
* @brief 独立按键扫描函数
*
* @return uchar 键值对应的元件位号
*/
uchar key_scan1(void)
{
uchar key = 0; //按键值
static bit key_up = 1; //按键松开标志,1松开0按下
if((key_up == 1) && (P30 == 0 || P31 == 0 || P32 == 0 || P33 == 0))
{
key_up = 0;
if(P30 == 0) key = 7;
else if(P31 == 0) key = 6;
else if(P32 == 0) key = 5;
else if(P33 == 0) key = 4;
return key;
}
else if(P30 == 1 && P31 == 1 && P32 == 1 && P33 == 1)
key_up = 1;
return 0;
}
/**
* @brief 矩阵键盘扫描函数
*
* @return uchar 键值对应的元件位号
*/
uchar key_scan2(void)
{
uchar key = 0; //按键值
static bit key_up = 1; //按键松开标志,1松开0按下
P44 = P42 = 1; //列扫描
P32 = P33 = 0;
if((key_up == 1)&&(P44 == 0 || P42 == 0))
{
if(P44 == 0) key = 7;
else if(P42 == 0) key = 11;
else return 0;
key_up = 0; //标志按下
P44 = P42 = 0;
P32 = P33 = 1; //行扫描
if(P32 == 0) key = key - 2;
else if(P33 == 0) key = key - 3;
return key;
}
else if(P44 == 1 && P42 == 1)
key_up = 1; //松开
return 0;
}
key.h
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
uchar key_scan1(void);
uchar key_scan2(void);
#endif
4、timer
存放定时器初始化和中断函数,包括定时器0测NE555频率、定时器1中断1ms任务调度,使用时注意与main.c的全局变量声明。
timer.c
#include "timer.h"
unsigned long systick_ms; //滴答定时器
uchar key_dly; //按键任务调度
uint display_dly; //显示任务调度
uint collect_dly; //采集任务调度
uchar pos; //数码管led扫描位置
uint count_1s; //1s计时测频率
uint fre; //频率
bit state_relay; //继电器状态
bit state_beep; //蜂鸣器状态
void Timer0_Init(void) //计数模式测方波频率@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设为计数模式
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //开启定时器1中断
// EA = 1; //开启总中断
}
void TIMER1_IRQHandler(void) interrupt 3
{
/* 任务调度处理 */
systick_ms++;
key_dly++;
display_dly++;
collect_dly++;
/* 测频率 */
if(++count_1s == 1000)
{
fre = (TH0 << 8) | TL0;
TH0 = 0;
TL0 = 0;
count_1s = 0;
}
/* 显示处理 */
smg(SMG,dot,pos);
led(LED,pos);
if(++pos == 8) pos = 0;
relay(state_relay);
beep(state_beep);
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
#include "display.h"
extern unsigned long systick_ms; //滴答定时器
extern uchar key_dly; //按键任务调度
extern uint display_dly; //显示任务调度
extern uint collect_dly; //采集任务调度
extern uchar pos; //数码管led扫描位置
extern uint count_1s; //1s计时测频率
extern uint fre; //频率
extern bit state_relay; //继电器状态
extern bit state_beep; //蜂鸣器状态
extern uchar SMG[];
extern uchar dot[];
extern uchar LED[];
void Timer0_Init(void);
void Timer1_Init(void);
#endif
5、iic
存放iic驱动函数,包括AT24C02、PCF8591的读写操作,使用时注意PCF8591读到的结果是上一次转换的值,多通道时要连续读两次。在进行ADC线性转换时,表达式中乘除相关的常量加个.0变成浮点型,否则整数相除可能四舍五入为0,如51.0/adc,而51/adc当51小于adc时,结果可能恒为0。AT24C02页写时while里每写一个字节加个I2C_Delay(200);,连续写时要加10ms左右延时。
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#define DELAY_TIME 10
sbit scl = P2^0; //时钟线
sbit sda = P2^1; //数据线
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
/**
* @brief AT24C02读一个字节
*
* @param addr 地址
* @return uchar 数据
*/
uchar AT24C02_read(uchar addr)
{
uchar dat;
I2CStart(); //起始信号
I2CSendByte(0xa0); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(addr); //发送通道地址
I2CWaitAck(); //等待应答
I2CStart(); //起始信号
I2CSendByte(0xa1); //发送器件地址(读)
I2CWaitAck(); //等待应答
dat = I2CReceiveByte(); //读数据
I2CSendAck(1); //不应答
I2CStop(); //停止信号
return dat;
}
/**
* @brief AT24C02页读,读取一页
*
* @param buf 接收数据数组首地址
* @param addr 内存地址,必须是8的整数倍,可以写十进制
* @param num 数据个数
*/
void AT24C02_read_page(uchar * buf,uchar addr,uchar num)
{
I2CStart(); //起始信号
I2CSendByte(0xa0); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(addr); //发送通道地址
I2CWaitAck(); //等待应答
I2CStart(); //起始信号
I2CSendByte(0xa1); //发送器件地址(读)
I2CWaitAck(); //等待应答
while(num--)
{
*buf++ = I2CReceiveByte();//接收数据
if(num)
I2CSendAck(0); //应答
else
I2CSendAck(1); //不应答
}
I2CStop();
}
/**
* @brief AT24C02写入一个字节
*
* @param addr 地址
* @param dat 数据
*/
void AT24C02_write(uchar addr,uchar dat)
{
I2CStart(); //起始信号
I2CSendByte(0xa0); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(addr); //发送通道地址
I2CWaitAck(); //等待应答
I2CSendByte(dat); //发送数据
I2CWaitAck(); //等待应答
I2CStop(); //停止信号
}
/**
* @brief AT24C02页写,写入一页数据
*
* @param buf 数据数组首地址
* @param addr 内存地址,必须是8的整数倍,可以写十进制
* @param num 数据个数
*/
void AT24C02_write_page(uchar * buf,uchar addr,uchar num)
{
I2CStart(); //起始信号
I2CSendByte(0xa0); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(addr); //发送通道地址
I2CWaitAck(); //等待应答
while(num--)
{
I2CSendByte(*buf++); //发送数据
I2CWaitAck(); //等待应答
}
I2CStop(); //停止信号
}
/**
* @brief PCF8591读AD
*
* @param control 0x00:AIN0,0x01:光敏,0x03:电位器
* @return uchar adc量化值,读到的是上次转换的值,读两个外设时要连续读两次
*/
uchar PCF8591_read(uchar control)
{
uchar dat;
I2CStart(); //起始信号
I2CSendByte(0x90); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(control); //发送通道地址
I2CWaitAck(); //等待应答
I2CStart(); //起始信号
I2CSendByte(0x91); //发送器件地址(读)
I2CWaitAck(); //等待应答
dat = I2CReceiveByte(); //读数据
I2CSendAck(1); //不应答
I2CStop(); //停止信号
return dat;
}
/**
* @brief PCF8591写DA
*
* @param control 只进行DA:0x40,AD/DA同时:0x40AIN0,0x41光敏,0x43电位器
* @param dat DA量化值,0-255对应0-5V
*/
void PCF8591_write(uchar control,uchar dat)
{
I2CStart(); //起始信号
I2CSendByte(0x90); //发送器件地址(写)
I2CWaitAck(); //等待应答
I2CSendByte(control); //发送通道地址
I2CWaitAck(); //等待应答
I2CSendByte(dat); //发送数据
I2CWaitAck(); //等待应答
I2CStop(); //停止信号
}
iic.h
#ifndef __IIC_H
#define __IIC_H
#include "sys.h"
uchar AT24C02_read(uchar addr);
void AT24C02_read_page(uchar * buf,uchar addr,uchar num);
void AT24C02_write(uchar addr,uchar dat);
void AT24C02_write_page(uchar * buf,uchar addr,uchar num);
uchar PCF8591_read(uchar control);
void PCF8591_write(uchar control,uchar dat);
#endif
6、ds1302
存放ds1302驱动函数,包括ds1302的读写,只保留了秒分时。
ds1302.c
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "ds1302.h"
sbit SCK = P1^7; //时钟线
sbit SDA = P2^3; //数据线
sbit RST = P1^3; //复位线
code uchar write_addr[3] = {0x80,0x82,0x84};//写地址
code uchar read_addr[3] = {0x81,0x83,0x85};//读地址
//时间: 秒, 分, 时, 日, 月, 周, 年
uchar Time[3] = {0x00,0x00,0x09};
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
/**
* @brief 写日期
*
*/
void ds1302_write(void)
{
uchar i;
Write_Ds1302_Byte(0x8e,0x00); //解除写保护
for(i = 0;i < 3;i++) //写数据
{
Write_Ds1302_Byte(write_addr[i],Time[i]);
}
Write_Ds1302_Byte(0x8e,0x80); //写保护
}
/**
* @brief 读日期
*
*/
void ds1302_read(void)
{
uchar i;
for(i = 0;i < 3;i++)
{
Time[i] = Read_Ds1302_Byte(read_addr[i]);
}
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include "sys.h"
extern uchar Time[];
void ds1302_write(void);
void ds1302_read(void);
#endif
7、onewire
存放ds18b20驱动函数,包括温度的读取,如果时序被中断频繁打乱可以在时序两端加上开关总中断(EA=0,1)。
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "onewire.h"
sbit DQ = P1^4; //数据线
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
/**
* @brief ds18b20温度读取
*
* @param dot 小数点位数,0:保留0位小数,1: 保留一位小数,2:保留两位小数
* @return uint 温度值,要配合小数点位数使用
*/
uint ds18b20_read(uchar dot)
{
uint temp; //温度值
uchar tml,tmh; //温度值低八位,高八位
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0x44); //开始温度转换
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0xbe); //读取暂存寄存器
tml = Read_DS18B20(); //读取低八位
tmh = Read_DS18B20(); //读取高八位
temp = (tmh << 8) | tml; //合并数据
switch (dot) //根据小数点位数设置精度
{
case 0: temp = temp * 0.0625;break;
case 1: temp = temp * 0.625;break;
case 2: temp = temp * 6.25;break;
}
return temp;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "sys.h"
uint ds18b20_read(uchar dot);
#endif
8、uart
存放串口驱动函数,包括串口初始化、收发、中断等。
uart.c
#include "uart.h"
uchar uart_rxbuf[10]; //串口接收数组
uchar uart_rxindex; //串口接收数组索引
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; // 允许串口中断
}
void UART1_IRQHandler(void) interrupt 4
{
if(RI)
{
if(uart_rxindex == 10)
uart_rxindex = 0;
uart_rxbuf[uart_rxindex++] = SBUF;
RI = 0;
}
}
char putchar(char ch)
{
SBUF = ch;
while (TI == 0); // 等待发送完成
TI = 0; // 发送完成标志位置0
return ch;
}
uart.h
#ifndef __UART_H
#define __UART_H
#include "sys.h"
extern uchar uart_rxbuf[];
void Uart1_Init(void);
#endif
9、ultrasound
存放超声波测距函数。
ultrasound.c
#include "ultrasound.h"
sbit TX = P1^0; //发射引脚
sbit RX = P1^1; //接收引脚
uchar read_distance(void)
{
uchar distance,num = 10;
// TX引脚发送40KHz方波信号驱动超声波发送探头
TX = 0;
CL = 0xF3; //设置定时初值
CH = 0xFF; //设置定时初值
CR = 1; //定时器计时
while(num--)
{
while(!CF);
TX ^= 1;
CL = 0xF3; //设置定时初值
CH = 0xFF; //设置定时初值
CF = 0;
}
//RX引脚接收时间计时计算距离
CR = 0;
CL = 0; //设置定时初值
CH = 0; //设置定时初值
CR = 1;
while(RX && !CF); //等待收到脉冲
CR = 0;
if(CF) //发生溢出
{
CF = 0;
distance = 255;
}
else //计算距离
distance = ((CH<<8)+CL)*0.017;
return distance;
}
ultrasound.h
#ifndef __ULTRASOUND_H
#define __ULTRASOUND_H
#include "sys.h"
uchar read_distance(void);
#endif
四、源码
通过网盘分享的文件:蓝桥杯单片机真题练习
链接: https://pan.baidu.com/s/1vFd_uWY6sLZUkyaXt0wdkw?pwd=7few 提取码: 7few
五、内存不够
使用的时候把不用的外设驱动删掉,尤其是串口接收数组占了很大内存。
实在不够就定义到idata或xdata。具体操作文章:
内存不够