**數組
第十一屆藍橋杯單片機省賽2020年四月份模擬試題
**緩存
i2c.c
#include "i2c.h" #include "intrins.h" #include "STC15F2K60S2.H" #define DELAY_TIME 5 #define SlaveAddrW 0xA0 #define SlaveAddrR 0xA1 //總線引腳定義 sbit SDA = P2^1; /* 數據線 */ sbit SCL = P2^0; /* 時鐘線 */ void IIC_Delay(unsigned char i) { do{_nop_();} while(i--); } //總線啓動條件 void IIC_Start(void) { SDA = 1; SCL = 1; IIC_Delay(DELAY_TIME); SDA = 0; IIC_Delay(DELAY_TIME); SCL = 0; } //總線中止條件 void IIC_Stop(void) { SDA = 0; SCL = 1; IIC_Delay(DELAY_TIME); SDA = 1; IIC_Delay(DELAY_TIME); } //發送應答 //void IIC_SendAck(bit ackbit) //{ // SCL = 0; // SDA = ackbit; // 0:應答,1:非應答 // IIC_Delay(DELAY_TIME); // SCL = 1; // IIC_Delay(DELAY_TIME); // SCL = 0; // SDA = 1; // IIC_Delay(DELAY_TIME); //} //等待應答 bit IIC_WaitAck(void) { bit ackbit; SCL = 1; IIC_Delay(DELAY_TIME); ackbit = SDA; SCL = 0; IIC_Delay(DELAY_TIME); return ackbit; } //經過I2C總線發送數據 void IIC_SendByte(unsigned char byt) { unsigned char i; for(i=0; i<8; i++) { SCL = 0; IIC_Delay(DELAY_TIME); if(byt & 0x80) SDA = 1; else SDA = 0; IIC_Delay(DELAY_TIME); SCL = 1; byt <<= 1; IIC_Delay(DELAY_TIME); } SCL = 0; } //從I2C總線上接收數據 unsigned char IIC_RecByte(void) { unsigned char i, da; for(i=0; i<8; i++) { SCL = 1; IIC_Delay(DELAY_TIME); da <<= 1; if(SDA) da |= 1; SCL = 0; IIC_Delay(DELAY_TIME); } return da; } void init_pcf8591() { IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(0x03); IIC_WaitAck(); IIC_Stop(); } unsigned char read_pcf8591() { unsigned char datas; IIC_Start(); IIC_SendByte(0x91); IIC_WaitAck(); datas=IIC_RecByte(); IIC_WaitAck(); IIC_Stop(); return datas; } void write_at24c02(unsigned char add,unsigned char datas) { IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(datas); IIC_WaitAck(); IIC_Stop(); } unsigned char read_at24c02(unsigned char add) { unsigned char datas; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0xa1); IIC_WaitAck(); datas=IIC_RecByte(); IIC_WaitAck(); IIC_Stop(); return datas; }
i2c.h
#ifndef _i2c_h_ #define _i2c_h_ #include "intrins.h" #include "STC15F2K60S2.H" void IIC_Delay(unsigned char i); void IIC_Start(void); void IIC_Stop(void); bit IIC_WaitAck(void); //void IIC_SendAck(bit ackbit); void IIC_SendByte(unsigned char byt); unsigned char IIC_RecByte(void); void init_pcf8591(void); unsigned char read_pcf8591(void); void write_at24c02(unsigned char add,unsigned char datas); unsigned char read_at24c02(unsigned char add); #endif
definit.h
#ifndef _definit_h_ #define _definit_h_ #ifndef u8 #define u8 unsigned char #endif #ifndef u16 #define u16 unsigned int #endif #include "STC15F2K60S2.H" void led(u8 i) //重定義 { P2&=0x1f; P2|=0x80; P0=i; } void relay(u8 i) { P2&=0x1f; P2|=0xa0; if(i) P0|=0x10; else P0&=0xef; } void buzzer(u8 i) { P2&=0x1f; P2|=0xa0; if(i) P0|=0x40; else P0&=0xbf; } #endif
main.c
#include "STC15F2K60S2.H" #include "definit.h" #include "i2c.h" u8 count; //計數 char Referenc;//參考電壓 擴大了10倍 00.0-50.0 u8 moshi;//模式 u8 key_error;//錯誤按鍵 u8 time; //5秒計時 u8 keys,keyse=0;//按鍵 u8 AIN3; //電壓保存比較 bit L1;//LED1 bit cycle; //循環判斷 u8 code sumaguan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; u8 number[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//緩存數組 void delay1ms(u16 i) //延時 void close() //上電初始化 void led_control() //LED控制函數 void Timer0Init(void) //50毫秒@12.000MHz void pcf_8591() //電壓處理顯示函數 void show() //數碼管顯示函數 void key() //按鍵檢測 void moshi1() //測量界面 void moshi2() //參數設置界面 void moshi3() //計數界面 void main() { close(); init_pcf8591(); //pcf8591初始化 Timer0Init(); //定時器初始化 Referenc=read_at24c02(0x00); //讀設置 while(1) { switch(moshi) { case(0):moshi1();break; //測量界面 case(1):moshi2();break; //參數設置 case(2):moshi3();break; //計數界面 } } } void delay1ms(u16 i) { u16 x; for(;i>0;i--) { for(x=850;x>0;x--); } } void close() { u8 i; for(;i<8;i++) number[i]=0xff; led(0xff); relay(0); buzzer(0); } void led_control() //LED控制函數 { u8 i=0xff; if(L1) i&=0xfe; else i|=0x01; if(count%2!=0) i&=0xfd; else i|=0x02; if(key_error>=3) i&=0xfb; else i|=0x04; led(i); } void Timer0Init(void) //50毫秒@12.000MHz { AUXR &= 0x7F; //定時器時鐘12T模式 TMOD &= 0xF0; //設置定時器模式 TMOD |= 0x01; //設置定時器模式 TL0 = 0xB0; //設置定時初值 TH0 = 0x3C; //設置定時初值 TF0 = 0; //清除TF0標誌 TR0 = 1; //定時器0開始計時 ET0=0; EA=1; } void timer0ser() interrupt 1 { TMOD &= 0xF0; //設置定時器模式 TMOD |= 0x01; //設置定時器模式 time++; if(time==100) {time=0;L1=1;ET0=0;}//定時5秒 } void pcf_8591() //電壓處理顯示函數 { // u8 i; float datase; u16 datas; datase=read_pcf8591(); datas=(datase/51)*100; AIN3=datas/10; number[0]=0xc1; //顯示U number[5]=sumaguan[datas/100]&0x7f; number[6]=sumaguan[datas%100/10]; number[7]=sumaguan[datas%10]; } void show() //數碼管顯示函數 { u8 i; for(i=0;i<8;i++) { P2&=0x1f; P2|=0xc0; P0=0x01<<i; P2&=0x1f; P2|=0xe0; P0=number[i]; delay1ms(3); P0=0xff; } } void key() //按鍵檢測 { if(keyse==0) P3=0x0f; switch(keyse) { case(0):if(P3!=0x0f) keyse++; break; //第一次判斷是否按下 case(1): //第二次確認按下並肯定具體按鍵 if(P3!=0x0f) { if(P3==0x0b) keys=1; //第三排 else if(P3==0x07) keys=2; //最後一排 // else keys=0; //不是後兩排 P3=0xf0; if(P3==0xd0) {if(keys==1) keys=13; else if(keys==2) keys=12;} else if(P3==0xe0) {if(keys==1) keys=17; else if(keys==2) keys=16;} keyse++; } else keyse=0; break; case(2): if(P3==0xf0) keyse=0;break; //肯定是否鬆手 } } void moshi1() //測量界面 { cycle=1; close(); while(cycle) { key(); show(); pcf_8591(); led_control(); if(ET0==0) {if(AIN3<Referenc) {ET0=1;time=0;}} if(AIN3>=Referenc) {ET0=0;L1=0;} if((keys==13)|(keys==16)|(keys==17)) {keys=0;key_error++;} if(keys==12) {cycle=0;keys=0;key_error=0;moshi=1;} } } void moshi2() //參數設置 { cycle=1; close(); while(cycle) { key(); show(); led_control(); if(keys==16) {keys=0;Referenc+=5;key_error=0;if(Referenc==55) Referenc=0;} if(keys==17) {keys=0;Referenc-=5;key_error=0;if(Referenc<0) Referenc=50;} if(keys==13) {keys=0;key_error++;} if(keys==12) {cycle=0;keys=0;key_error=0;moshi=2;write_at24c02(0x00,Referenc);} number[0]=0x8c; //顯示P number[5]=sumaguan[Referenc/10]&0x7f; number[6]=sumaguan[Referenc%10]; number[7]=sumaguan[0]; } } void moshi3() //計數界面 { u8 i=0; u16 datas; float datase; cycle=1; close(); while(cycle) { key(); show(); led_control(); datase=read_pcf8591(); datas=(datase/51)*100; switch(i) //降低波形電壓判斷 { case(0): if(datas>=Referenc) i++;break; case(1): if(datas<Referenc) {i=0;count++;}break; } // if(ET0==0) {if(datas<Referenc) {ET0=1;time=0;}} // if(datas>=Referenc) {ET0=0;L1=0;} if(keys==13) {keys=0;count=0;} if((keys==16)|(keys==17)) {keys=0;key_error++;} if(keys==12) {cycle=0;keys=0;key_error=0;moshi=0;} number[0]=0xc8; //顯示N number[5]=0xff; number[6]=sumaguan[count/10]; number[7]=sumaguan[count%10]; } }