文章目录
- 前言
- 效果
- 代码树
-
- init.c
- main.c
- onewire.c
- iic.c
- ds1302.c
- init.h
- onewire.h
- iic.h
- ds1302.h
- type.h
- 交流群
前言
所有功能都实现了。说实话,这个国家赛题的串口和eeprom它仍然很具挑战性。这部分需要更多的练习和注意;对于一些常见的操作,我们应该多总结一下,以便在比赛中使用。保存信息时,不要保存字符串!直接保存变量(uchar)可以。我只想提一些需要注意的地方。
- 一是要注意strcpy和memcpy区别在于字符串的复制和内存的复制。字符串的复制不能用于数组的复制,因为一旦数组中出现0,就会识别出空字符!
- 注意数组的大小是否可以安装格式化字符串!
- 第二个是eeprom的处理,eeprom分为32页,一页8页Byte,因此,它可以通过页面写作来保存。例如,您的起始地址为0,即第一页,起始位置为8,为第二页。我发现在使用页面写作后,写作和阅读仍然有一些问题,所以我使用了一种特殊的方法来处理它。这部分可以通过程序来理解
- 不要写字符串数据的接收和判断。例如,我发送的数据不一定是6位数据。如果数据宽度不同,写字的程序必然会导致错误。这也可以从我的字符串处理部分来理解。
- 我不发标题,网上都有。
效果
说了这么多,看看效果。
注意声音有点大,不好意思录进去
蓝桥杯单片机第五届国赛题目-多功能事件记录器演示
代码树
init.c
#include "init.h" extern uchar bf[8]; void SL(uchar _dev, uchar _data) {
P0 = _data; SEL(_dev); } void Timer1Init(void) //2毫秒@12.000MHz {
AUXR |= 0x40; //定时器时钟1T模式 TMOD &= 0x0F; //设置定时器模式 TL1 = 0x40; ///设定时初值 TH1 = 0xA2; ///设定时初值 TF1 = 0; //清除TF1标志 TR1 = 1; ///定时器1开始计时 ET1 = 1; EA = 1; } uchar GetKey() {
if(K3 == 0) return 5; if(K4 == 0) return 4;
return 0;
}
void TimeRun(t_delay* time)
{
if(time->cnt++ < time->max);
else
{
time->cnt = 0;
time->ok = 1;
}
}
uchar FR(float _data, uchar _dig)
{
uint i = 1;
while(_dig--)
{
i = i*10;
}
return((uint)_data/i%10);
}
void Bf(uchar _0, uchar _1, uchar _2, uchar _3,
uchar _4, uchar _5, uchar _6, uchar _7)
{
bf[0] = _0; bf[1] = _1; bf[2] = _2; bf[3] = _3;
bf[4] = _4; bf[5] = _5; bf[6] = _6; bf[7] = _7;
}
void UartInit(void) //1200bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0x3C; //设定定时初值
T2H = 0xF6; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1;
}
void print(uchar* string)
{
ES = 0; TI = 1;
printf("%s", string);
TI = 0; ES = 1;
}
uchar LedChange(uchar _data, uchar _dig, uchar _state)
{
//LED的状态是反着来的
if(!_state)
{
_data |= 1 << _dig;
}
else
{
_data &= ~(1 << _dig);
}
SL(4, _data);
return _data;
}
main.c
#include "init.h" enum{ LED=4, EXT, SEL, CODE}; code uchar CA[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xc6, 0x89, 0xbf}; uchar bf[] = { 1, 2, 3, 4, 5, 6, 7, 8}; uchar curDig = 0; uchar enprint = 0; uchar key, tmpKey, keyCnt; enum{ KS_GT, KS_AS, KS_WA};keyState=KS_GT; t_delay delay_200 = { 200, 0, 0}; t_delay tx_delay = { 50, 0, 0}; t_delay cnt_65535 = { 65535, 0, 0}; uchar index = 0; uchar xdata rxBuf[20] = "0"; //发送缓冲不能小了,要避免出现其他异常情况将发送缓冲装溢出了 uchar xdata txBuf[30] = "0"; uchar revCorrect = 0; uchar time[3]; uchar jieJin = 0; uchar Second = 255; //事件接近的时间 uchar timeCnt = 0; //模式 enum{ S_AUTOT, S_AUTOR}gloSta = S_AUTOT; //显示模式 enum{ DIS_WSD, DIS_TIME, DIS_ITEM}disMode = DIS_WSD; uchar ledData = 0xfe; float adcVal, adc1Val; uchar storeData[5][7] = { 0}; //调试使用 //uchar storeData1[5][6] = { {1,2,3, 4 ,5 ,25}, // {1,2,3, 4 ,5 ,25}, // {1,2,3, 4 ,5 ,25}, // {1,2,3, 4 ,5 ,25}, // {1,2,3, 4 ,5 ,25}}; void Timer1Hanle() interrupt 3 { SL(CODE, 0xff);SL(SEL, 1 << curDig); SL(CODE, CA[bf[curDig]]); curDig = (curDig + 1)%8; switch(keyState) { case KS_GT: keyCnt = 0; tmpKey =GetKey(); keyState = KS_AS; break; case KS_AS: if(keyCnt++ < 10); else if(tmpKey == GetKey()) { if(tmpKey != key) { key = tmpKey;keyState = KS_WA; } else { keyState = KS_GT; } } else { keyState = KS_GT; } break; } TimeRun(&delay_200); if(tx_delay.ok == 2) TimeRun(&tx_delay); //如果允许计算时间 if(cnt_65535.ok == 2) TimeRun(&cnt_65535); } void Sensor() { if(delay_200.ok == 1) { delay_200.ok = 0; Temp_Read(); adcVal = ADC_Read(0x43, 0); adc1Val = ADC_Read(0x41, 0); if(adc1Val < 50) { jieJin = 1; ledData = LedChange(ledData, 2, 1); //如果计时没有开始,那么让计时开始 if(cnt_65535.cnt == 0) cnt_65535.ok = 2; } else { jieJin = 0; ledData = LedChange(ledData, 2, 0); //如果已经开始计时,那么停止 if(cnt_65535.cnt != 0) { uchar tmpString[7]; cnt_65535.ok = 0; timeCnt = cnt_65535.cnt*2/1000; tmpString[0] = (uint)tempVal/100; tmpString[1] = (uint)adcVal; tmpString[2] = time[2]; tmpString[3] = time[1]; tmpString[4] = time[0]; tmpString[5] = timeCnt; stack(tmpString); cnt_65535.cnt = 0; } } DS1302_Read(); } } void UartHandle() interrupt 4 { if(TI) TI = 0; if(RI) { RI = 0; //如果进来的时候是第一次,因此开启计时 if(tx_delay.ok == 0) tx_delay.ok = 2; //进来是因为串口接收中断 if(index < 20) { rxBuf[index++] = SBUF; } } } void UartProcess() { //如果接收超时,触发检查事件 //如果进来的时候是因为计时结束 if(tx_delay.ok == 1) { //结束标志清零 tx_delay.ok = 0; //如果接收的数据是6位 if(index == 6) { //如果口令正确 if(strncmp(rxBuf, "AAASSS", 6) == 0) { enprint = 1; } } //如果口令不是正确的,那么就是错误的 else { enprint = 2; } //不管哪种情况,都需要将index清空 index = 0; } //如果口令正确 if(enprint == 1) { uchar i; enprint = 0; //根据状态来选择串口的输出 switch(gloSta) { case S_AUTOT: //开启串口输出 revCorrect = 1; break; case S_AUTOR: for(i = 0; i < 5; i++) { uchar temp[25] = { 0}; sprintf(temp, "{%bu-%bu%%}-{%bu-%bu-%bu}{%bu}\r\n", storeData[i][0], storeData[i][1], storeData[i][2], storeData[i][3], storeData[i][4], storeData[i][5]); print(temp); //很重要,不然会联结 Delay8ms(); } break; } //如果口令不正确关闭输出 } else if(enprint == 2) { enprint = 0; revCorrect = 0; } } void EventProcess() { if(revCorrect) { //如果一秒到了 if(Second != time[0]) { //发送相应命令 Second = time[0]; sprintf(txBuf, "{%.0f-%.0f%%}-{%bu-%bu-%bu}{%bu}\r\n", tempVal/100.0, adcVal, time[2], time[1], time[0], jieJin); print(txBuf); } } } //按键处理 void keyProcess() { switch(key) { case 4: gloSta = (gloSta == S_AUTOT)?S_AUTOR:S_AUTOT; //互
锁的先关闭所有,再根据条件开启响应的led ledData = LedChange(ledData, 1, 0); ledData = LedChange(ledData, 0, 0); if(gloSta == S_AUTOR) { revCorrect = 0; ledData = LedChange(ledData, 1, 1); } else { ledData = LedChange(ledData, 0, 1); } break; case 5: if(disMode == DIS_WSD) disMode = DIS_TIME; else if(disMode == DIS_TIME) disMode = DIS_ITEM; else disMode = DIS_WSD; break; } } void DisProcess() { switch(disMode) { case DIS_WSD: Bf(FR(tempVal, 3), FR(tempVal, 2), F_CC, F_C, F_C, FR(adcVal, 1), FR(adcVal, 0), F_H); break; case DIS_TIME: Bf(FR(time[2], 1), FR(time[2], 0), F_SEP, FR(time[1], 1), FR(time[1], 0), F_SEP, FR(time[0], 1), FR(time[0], 0)); break; case DIS_ITEM: Bf(F_C, F_C, F_C, F_SEP, FR(timeCnt, 3), FR(timeCnt, 2), FR(timeCnt, 1), FR(timeCnt, 0)); break; } } //非常重要 void Delay8ms() //@12.000MHz { unsigned char i, j; i = 94; j = 95; do { while (--j); } while (--i); } void stack(uchar* string) { uchar i = 0; for(; i < 4; i++) { memcpy(storeData[i], storeData[i+1], 6); } memcpy(storeData[i], string, 6); for(i = 0; i < 5; i++) { EEPROM_Write(i*8, storeData[i], 6); EEPROM_Write(i*8, storeData[i], 6); EEPROM_Write(i*8, storeData[i], 6); } } void StoreInit() { uchar i = 0; //调试使用 // for(i = 0; i < 5; i++) // { // EEPROM_Write(i*8, storeData1[i], 7); // EEPROM_Write(i*8, storeData1[i], 7); // EEPROM_Write(i*8, storeData1[i], 7); // } for(i = 0; i < 5; i++) { uchar tmpData[6]; EEPROM_Read(i*8, 6, storeData[i]); EEPROM_Read(i*8, 6