目录
外设的考察
本套题目考到的外设除了三大金刚(按键、数码管、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;
}