蓝桥杯单片机组的各模块代码总结(供参考学习)

这是蓝桥杯单片机组各常考的使用以及总结,供新手朋友参考学习,如有错误,请批评指正。

//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

最后请大家点个赞和关注吧,谢谢。 

你可能感兴趣的:(蓝桥杯单片机,单片机,蓝桥杯,学习)