这是蓝桥杯单片机组各常考的使用以及总结,供新手朋友参考学习,如有错误,请批评指正。
//IIC.h
//添加头文件 并且函数声明
#include "STC15F2K60S2.h"
#include "intrins.h"
u8 read_24c02(u8 add);
void write_24c02(u8 add,u8 data1);
u8 read_pcf8591(void);
void write_pcf8591(u8 data1);
//IIC.C
//用Delay5us()替换IIC_Delay(DELAY_TIME)
void Delay5us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 12;
while (--i);
}
u8 read_24c02(u8 add)
{
u8 temp;
IIC_Start(); //起始信号
IIC_SendByte(0xa0);//设备写
IIC_WaitAck();//等待应答
IIC_SendByte(add);//写入内容地址
IIC_WaitAck();//等待应答
IIC_Start();//起始信号
IIC_SendByte(0xa1);//设备读
IIC_WaitAck();//等待应答
temp=IIC_RecByte();//读取一字节数据
IIC_SendAck(1);//发送非应答
IIC_Stop();//停止信号
return temp;//返回值
}
void write_24c02(u8 add,u8 data1)
{
IIC_Start();//起始信号
IIC_SendByte(0xa0);//设备写
IIC_WaitAck();//等待应答
IIC_SendByte(add);//发送内容地址
IIC_WaitAck();//等待应答
IIC_SendByte(data1);//发送数据
IIC_WaitAck();//等待应答
IIC_Stop();//停止信号
}
//连续写AT24C02要延时5ms
u8 read_pcf8591(void)
{
u8 temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);//0x03控制字节 是将AIN3接到转换通道channel_3,并启动转换通道3转换
//0x01也是同理
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void write_pcf8591(u8 data1)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(data1);
IIC_WaitAck();
IIC_Stop();
}
//onewire.h
//声明函数float rd_temperature(void)
//onewire.c
void Delay_OneWire(unsigned int t) //添加一个for循环
{
char i;
while(t--)
{
for(i=0;i<12;i++);
}
}
float rd_temperature()
{
u16 low,high,temp;
Init_DS18B20(); //初始化
Delay_OneWire(1); //延迟
Write_DS18B20(0xcc); //跳过ROM取消设备地址验证
Write_DS18B20(0x44); //启动温度转换
Init_DS18B20();
Delay_OneWire(1);
Write_DS18B20(0xcc); //跳过ROM取消设备地址验证
Write_DS18B20(0xbe); //读取寄存器
low=Read_DS18B20(); //先读取低8位
high=Read_DS18B20(); //读取高八位
temp=(high<<8)|low; //得到寄存器的数值
return temp*0.0625; //数字量回归成模拟量
}
//DS1302.H
void set_sfm(uchar shi,uchar fen,uchar miao);
//DS1302.C
void set_sfm(uchar shi,uchar fen,uchar miao)
{
Write_Ds1302_Byte(0x8e,0); //关闭写保护
Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10); //转换成BCD码再储存
Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10);
Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10);
Write_Ds1302_Byte(0x8e,0x80); //打开写保护
}
EA=0;
miao=Read_Ds1302_Byte(0x81);
fen=Read_Ds1302_Byte(0x83);
shi=Read_Ds1302_Byte(0x85);
EA=1;
miao=miao/16*10+miao%16;
shi=shi/16*10+shi%16;
fen=fen/16*10+fen%16;
//按键状态扫描
//分为独立按键 矩形按键 定时长按
//-----------------------------------------------//状态扫描矩阵按键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
unsigned char read_KBD(void)
{
static char key_state = 0;
unsigned char key_return=0, key_press;
unsigned char key1,key2;
P44=1;P42=1;P35=1;P34=1;P33=0;P32=0;P31=0;P30=0;
if(P44==0) key1=0x70;
else if(P42==0) key1=0xb0;
else if(P35==0) key1=0xd0;
else if(P34==0) key1=0xe0;
else key1=0xf0;
P44=0;P42=0;P35=0;P34=0;P33=1;P32=1;P31=1;P30=1;
if(P33==0) key2=0x07;
else if(P32==0) key2=0x0b;
else if(P31==0) key2=0x0d;
else if(P30==0) key2=0x0e;
else key2=0x0f;
key_press =key1|key2;
switch (key_state)
{
case key_state_0:
if (key_press!=0xff) key_state = key_state_1;
break;
case key_state_1:
if (key_press !=0xff)
{
if(key_press==0x77) key_return = 4;
if(key_press==0x7b) key_return = 5;
if(key_press==0x7d) key_return = 6;
if(key_press==0x7e) key_return = 7;
if(key_press==0xb7) key_return = 8;
if(key_press==0xbb) key_return = 9;
if(key_press==0xbd) key_return = 10;
if(key_press==0xbe) key_return = 11;
if(key_press==0xd7) key_return = 12;
if(key_press==0xdb) key_return = 13;
if(key_press==0xdd) key_return = 14;
if(key_press==0xde) key_return = 15;
if(key_press==0xe7) key_return = 16;
if(key_press==0xeb) key_return = 17;
if(key_press==0xed) key_return = 18;
if(key_press==0xee) key_return = 19;
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0xff) key_state = key_state_0;
break;
}
return key_return;
}
//-----------------------------------------------//状态扫描独立按键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
unsigned char read_KBD(void)
{
static char key_state = 0;
unsigned char key_return=0, key_press;
P33=1;P32=1;P31=1;P30=1;
if(P33==0) key_press=0x07;
else if(P32==0) key_press=0x0b;
else if(P31==0) key_press=0x0d;
else if(P30==0) key_press=0x0e;
else key_press=0x0f;
switch (key_state)
{
case key_state_0:
if (key_press!=0x0f) key_state = key_state_1;
break;
case key_state_1:
if (key_press !=0x0f)
{
if(key_press==0x07) key_return = 4;
if(key_press==0x0b) key_return = 5;
if(key_press==0x0d) key_return = 6;
if(key_press==0x0e) key_return = 7;
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0x0f) key_state = key_state_0;
break;
}
return key_return;
}
//定时长按
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
u8 j=0; //按键长按1s
bit s8_flag=0;
unsigned char read_KBD(void)
{
static char key_state = 0;
unsigned char key_return=0, key_press;
unsigned char key1,key2;
P44=1;P42=1;P33=0;P32=0;
if(P44==0) key1=0x70;
else if(P42==0) key1=0xb0;
else key1=0xf0;
P44=0;P42=0;P33=1;P32=1;
if(P33==0) key2=0x07;
else if(P32==0) key2=0x0b;
else key2=0x0f;
key_press =key1|key2;
switch (key_state)
{
case key_state_0:
if (key_press!=0xff) key_state = key_state_1;
break;
case key_state_1:
if (key_press !=0xff)
{
if(key_press==0x77) key_return = 4;
if(key_press==0x7b) key_return = 5;
// if(key_press==0xb7) key_return = 8; ①
if(key_press==0xbb) key_return = 9;
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0xff) //松开全部按键
{
key_state = key_state_0; //归位
if(j>0&&j<99) key_return = 8; //按下s8后,key_press=0xb7,j=0,然后执行j++,所以只要满足0=99时 j++不用执行了,j就不会一直自加然后归零 这样往复
else if(j==99) {s8_flag=1; j++;} //当j=99时 说明过了大约一秒 我们执行长按结果,j自加到100.
}
break;
}
return key_return;
}
//定时器计数模式测ne555频率
//定时器0计数模式 通过P34输入脉冲
TMOD =0x04; //设置定时器模式 0000 0100 定时器0计数,定时器1定时 都是16位自动重装
TL0=0X00;//计数器清零
TH0=0X00;
TF0 = 0; //清除TF0溢出标志
ET0=0;//溢出中断允许位 关闭定时器0中断
//在定时器1中断服务函数里计算脉冲频率
if (count_t == 500) //500ms计算一次数据
{
count_t=0;
TR0=0; //关闭定时器0
DATA_f=(TH0*256+TL0)*2; //计算1s脉冲次数
TH0=0;TL0=0; //初始化计数值
TR0=1; //打开定时器0
}
//P25 P26 P27控制74HC138输出时 编写代码严格点
P2=(P2&0X1F)|0XA0;P0=0X00;P2&=0X1F;//关闭蜂鸣器 继电器
P2=(P2&0X1F)|0X80;P0=0XFF;P2&=0X1F;//关闭led
//IIC协议连续读写时 要延时5ms
//必要的时候要关闭总中断
//串口通讯
//可用isp生成,使用定时器2,1T,16位自动重装载模式
void UartInit(void) //[email protected]
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0x8F; //设定定时初值
T2H = 0xFD; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES=1; //自己写,打开串口中断
}
void send_byte(unsigned char dat)
{
SBUF=dat;
while(TI==0); //等待发送标志位 置1
}
void sendstring(unsigned char *s)
{
while(*s!='\0') //检查是否到结尾
{
send_byte(*s++);//地址递增进行逐个发送
}
}
void usart1() interrupt 4 //中断号4
{
TI=0; //当TI=1时 把TI置零;TI等于0时 同样把TI置0不影响什么
if(RI==1)
{
RI=0;
Rdat=SBUF; //接收一个字符
}
}
//如果是接收字符串命令
void usart1() interrupt 4 //中断号4
{
static u8 i=0;
u8 k=0;
TI=0; //当TI=1时 把TI置零;TI等于0时 同样把TI置0不影响什么
if(RI==1)
{
RI=0;
Rdat[i]=SBUF; //接收一个字符 ①
i++;
if(i==15)i=0;
for(k=0;k<12;k++)//寻找连续4个的 st\r\n 字符 ②
{
if(Rdat[0+k]=='S')
if(Rdat[1+k]=='T')
if(Rdat[2+k]=='\r')
if(Rdat[3+k]=='\n')
{usart_flag=0x01;break;}
}
if(usart_flag!=0) //如果搜寻到usart_flag就!=0,初始化Rdat[14]
{
for(i=0;i<15;i++)
{
Rdat[i]=0;
}
i=0;
}
}
}
//串口发送字符串
sendstring(unsigned char *s);
//或者发送带有数据的字符串,先将数据转化为字符串再发送
sprintf(output,"%d",(u16)data); //char output[50]=0;
sendstring(output);
//超声波测距
sbit RX=P1^1;
sbit TX=P1^0;
//将定时器1用来测距离
AUXR &= 0xbf;//配置成12T模式,
TMOD = 0x10;//定时器1 16位不自动重装载
TF1=0;//溢出中断标志位置0
TH1 = 0;
TL1 = 0;//初值为0
void Sendwave(void)
{
u8 i;
for(i=0;i<8;i++)
{
TX=1;
Delay10us();
TX=0;
Delay10us(); //约为40khz
}
}
u16 Measure_Distance()
{
u16 time,distance;
Sendwave();
TR1=1;
while((TF1==0)&&(RX==1));
TR1=0;
if(TF1==1)
{
TF1=0;
distance=999;
}
else
{
time=TH1*256+TL1;
distance=(u16)(time*0.017);
}
TH1=0;TL1=0;
return distance;
}
//写LED时可定义变量 led=0xff
//或者定义LED数组 unsigned char led[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//使用的时候取反使用,当led有点问题的时候注意消隐(P2=(P2&0X1F)|0X80;P0=0xff;P2&=0X1F;)
//同理数码管显示时出现问题(没用到的数码管有微弱灯光)也要注意消隐(P2=(P2&0X1F)|0Xe0;P0=0xff;P2&=0X1F;)
//PWM输出——改变占空比
//题目告诉PWM信号频率,比如1Khz那么PWM周期为1ms 我们可以设置定时器的中断周期为0.1ms
count++;
if(count
最后请大家点个赞和关注吧,谢谢。