蓝桥杯单片机第九届国赛,注意点!!!

本文详细介绍了PCF8591的使用、NE555定时器配置,以及EEPROM的存储操作,特别是针对按键S6的短按和长按处理以及EEPROM数据的读写问题。作者还提供了相关代码示例,展示了如何在嵌套界面和中断服务函数中实现这些功能。
摘要由CSDN通过智能技术生成

目录

外设的考察

 PCF8591

      NE555的配置

频率的测量

    难点

1、按键S6在阈值界面下分为短按和长按不松开

2-----EEPROM的储存

EEPROM底层的书写

按页写入

按页读取

相关代码展示


外设的考察

本套题目考到的外设除了三大金刚(按键、数码管、LED),

NE555,DS18b20,EEPROM,PCF8591

分析:几个界面并不困难,只是大界面里嵌套小界面和界面跳转罢了,考到NE555是会占用定时器0,所以我们用定时器1扫描,不要忘记NE555的配置,然后是PCF8591;这个我们把它放在按键减速函数里面,
最后是我认为本套题目中的大BOSS----->EEPROM(今天折磨了我几个小时,因为不知道为什么我的温度老是存不进EEPROM),最后我会好好讲讲

 PCF8591


void Key_Process()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 0;
    
*/    Rb2_Voltage = PCF8591_AD(0x43)/51.0;

    Key_Val = Key_Scan();
    


    
  NE555的配置

   从STC-isp上生成一个0ms的定时器0
void Timer0Init(void)        //0毫秒@12.000MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
    TMOD &= 0xF0;        //设置定时器模式
*/    TMOD |= 0x05;//----------------------------------------------关键

/*这里我们是将定时/计数器0从定时模式更改为技术模式*/
    TL0 = 0x00;        //设置定时初值
    TH0 = 0x00;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
}

 从STC-isp上生成一个1ms的定时器1
void Timer1Init(void)        //1毫秒@12.000MHz
{
    AUXR &= 0xBF;        //定时器时钟12T模式
    TMOD &= 0x0F;        //设置定时器模式
    TL1 = 0x18;        //设置定时初值
    TH1 = 0xFC;        //设置定时初值
    TF1 = 0;        //清除TF1标志
    TR1 = 1;        //定时器1开始计时
    ET1 = 1;
    EA = 1;
}

注:不要忘记在main函数里添加Timer0Init();和 Timer1Init();
中断部分:

频率的测量

在中断服务函数中测量

unsigned int CT_1000ms;

void Timer1() interrupt 3

{
     if(++CT_1000ms == 1000)
    {
        CT_1000ms = 0;
        Frequency = TH0<<8|TL0;
        TH0 = TL0 = 0;
    }

}

    
难点


1、按键S6在阈值界面下分为短按和长按不松开


*/短按:
if(Mode == 2)
{
        if(Key_Down == 6)
        {
            Long_Press_Flag = 1;
        }
        if(Key_Up == 6)//短按
        {
            if(CT_Long_Press <= 200)
            {    
//                Threshold_Disp += 0.1;                                 //这里不知道为什么如果我用float类范围是0.1-4.9
//                if(Threshold_Disp > 5.0) Threshold_Disp = 0.1;
                if(++Threshold_Disp > 50) Threshold_Disp = 1;   
            }
            Long_Press_Flag = 0;
            CT_Long_Press = 0;
        }
}
    
*/长按:
if(Key_Old == 6 && CT_Long_Press >= 800)
{
//        Threshold_Disp += 0.1;
//        if(Threshold_Disp > 5.0) Threshold_Disp = 0.1;
      if(++Threshold_Disp > 50) Threshold_Disp = 1;
}

定时器部分
void Timer1() interrupt 3
{
 if(Long_Press_Flag)
 {
    if(++CT_Long_Press == 800)
    {
       CT_Long_Press = 801;//卡住他
    }    
 }
}

2-----EEPROM的储存


在讲这个之前我们先讲讲EEPROM本身
大家可以思考这几个问题:
1.写完可以立刻读吗?
2.读完可以立刻写吗?
3.写完可以立刻写吗?
4.读完可以立刻读吗?

这个是我在浏览别人的文章时看到别人提出的问题
觉得很好,把他分享出来
经过一系列实验得出结论:
*/写完不能立刻读
读完可以立刻写
读完可以立刻读
*/写完不能立刻写

那么本套题我们就要将EEPROm的写入和读取函数分开
避免数据出错

EEPROM底层的书写

我们先来讲讲EEPROM底层的书写,这里我采用的是按页写入和读取

按页写入

/*入口参数:需要写入的的字符串,写入的地址(一定要为8的倍数(例如(0或8或16……))读取的数量)

函数功能:想EEPROM的某个地址写入字符串中特定数量的字符*/


void EEPROM_Write(unsigned char* EEPROM_String,unsigned char addr, unsigned char num )
{
    I2CStart();//开启发送信号
    I2CSendByte(0xa0);//选择EEPROM芯片,确定写的模式
    I2CWaitAck();//等待EEPROM反馈
    I2CSendByte(addr);//写入要存储的数据地址
    I2CWaitAck();//等待EEPROM反馈
    
    while(num--)
    {
        I2CSendByte(*EEPROM_String++);//将要写入的信息写入
        I2CWaitAck();//等待EEPROM反馈
        I2C_Delay(200);//这里要延时一下,因为写完不能立刻写
    }
    I2CStop();//停止发送
}

按页读取

void EEPROM_Read(unsigned char* EEPROM_String,unsigned char addr, unsigned char num )
{
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    
    I2CStart();
    I2CSendByte(0xa1);
    I2CWaitAck();
    
    while(num--)
    {
        *EEPROM_String++ = I2CReceiveByte();
        if(num)
            I2CSendAck(0);
        else
            I2CSendAck(1);
    }
    I2CStop();
}


相关代码展示


void Key_Process()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 0;
    
    Rb2_Voltage = PCF8591_AD(0x43)/51.0;
    Key_Val = Key_Scan();
    //三行按键法
    Key_Down =  Key_Val & (Key_Val ^ Key_Old);
    Key_Up   =  ~Key_Val&(Key_Val ^ Key_Old);
    Key_Old  =  Key_Val;
    
    switch(Key_Down)
    {
        case 5:
            if(Mode == 0)
            {
                temp_Echo_T = T*100;                 */将温度放大100倍保存
                EEPROM_Dat[0] = temp_Echo_T/256;
                EEPROM_Dat[1] = temp_Echo_T%256;
                EEPROM_Dat[2] = (uchar)(Rb2_Voltage*10);    */将电压放大10倍保存
                EEPROM_Dat[3] = Frequency/256;
                EEPROM_Dat[4] = Frequency%256;
                EEPROM_Write(EEPROM_Dat,0,5);
                  EEPROM_Flag = 1;                */辅助标志位       
            }
        break;
        case 6:
            if(Mode != 2)
            {
                if(EEPROM_Flag)
                {
                    S6_Flag = 1;
//                    EEPROM_Read(EEPROM_Dat,0,5);         //不可以在这里读  不然会出错
                        EEPROM_Flag = 0;
                    Echo_T = EEPROM_Dat[0]*256+EEPROM_Dat[1];
                    Echo_Rb2_Voltage = EEPROM_Dat[2]/10.0;
                    Echo_Frequency = EEPROM_Dat[3]*256+EEPROM_Dat[4];
                }
            Mode = 1; 
            }
        break;
    }
    
    
    
*/EEPROM在这里读
void SMG_Process()
{
    if(SMG_Slow_Down) return;
    SMG_Slow_Down = 0;
    //信息处理区
    if(S6_Flag)
    {
            S6_Flag = 0;
            EEPROM_Read(EEPROM_Dat,0,5);
    }
    
    T = Temperature_Read();
    
    //数码管显示部分
    
    
*/中断中的减速变量
void Timer1() interrupt 3
{
    if(++Key_Slow_Down == 10)  Key_Slow_Down =0;
    if(++SMG_Slow_Down == 500) SMG_Slow_Down =0;
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值