蓝桥杯
System
延时程序
延时函数均可由stc—isp生成 void delay_us(uint xus) //@12.000MHz void delay_ms(uint xms) //@12.000MHz
sys初始化
// hc573选择 void hc573(uchar channel) { switch(channel) { case 4: P2 = P2&0x1f | 0x80; break; case 5: P2 = P2&0x1f | 0xa0; break; case 6: P2 = P2&0x1f | 0xc0; break; case 7: P2 = P2&0x1f | 0xe0; break; } P2 = P2&0x1f; } void sys_init() // 关闭LEd和蜂鸣器,继电器 { P0 = 0xff; hc573(4); P0 = 0x00; hc573(5); }
Drivers
基本模块(三大金刚)
LED
void led_contral(uchar *q) { uchar i; uchar temp; for(i=0;i<8;i++) { if(q[i]) temp &= ~(0x01 << i); else temp|=0x01<<i; } P0 = temp; hc573(4); } // 可选择分别对 蜂鸣器 继电器选控 void beep_contral(bit enable); void relay_contral(bit enable);
SMG
// 定义一个SMG数组,方便使用。 code uchar segment[] = {}; // 直接对数组操作 void seg_contral(uchar *smg,uchar *dot) { uchar pos; P0 = 0xff; hc573(7); P0 = 0x01 << pos; hc573(6); if(dot[pos]) P0 = segment[smg[pos]] & 0x7f; else P0 = segment[smg[pos]]; hc573(7); pos = (pos + 1) % 8; }
KEy
// 注意独立按键和矩阵按键 uchar key_scan() { if((key_up==1)&&(P30==0||P31==0||P32==0||P33==0)) //独立按键有按键按下 { delay_ms(20); key_up = 0; if(P30==0) return 1; else if(P31==0) return 2; else if(P32==0) return 3; else if(P33==0) return 4; else return 0; } else if(P30==1&&P31==1&&P32==1&&P33==1)//独立按键有按键按下,已经松手 { key_up = 1; return 0; } else return 0; } uchar key_scan_2() { uchar key; P44 = P42 = P35 = P34 = 1; P30 = P31 = P32 = P33 = 0; if(key_up == 1 && (P44 == 0 || P42 == 0|| P35 ==0 || P34 == 0)) { delay_ms(20); if(P44 == 0 ) key = 1; else if (P42 == 0) key = 2; else if (P35 == 0) key = 3; else if (P34 == 0) key = 4; else return 0; P44 = P42 = P35 = P34 = 0; P30 = P31 = P32 = P33 = 1; if(P30 == 0) return key+0; else if (P31 == 0) return key+4; else if (P32 == 0) return key+8; else if (P33 == 0) return key+12; else return 0; } else key_up = 1; return 0; }
拓展模块 - - 一般只有省赛考
定时器 + 中断
// 用stc—isp可分别生成0,1,2的定时器 /* 定时器0中断初始化函数 */ void Timer0Init(void) //1毫秒@12.000MHz { AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //定时器中断0打开 EA = 1; //总中断打开 }
Ds18b20
初始化–发送跳过指令(0xcc)-- 发送温度转换(0x44)–初始化 – 发送跳过指令(0xcc)–发送读取温度寄存器(0xbe)-- 先后读取低->高八位温度数据,整合成16位数据,再返回temp
// 开机的85°,可以先在whlie前面读取一次温度,在延时750ms,即可消除 uint temp_read(uchar dot) { uint temp; uchar tmh,tml; init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0x44); init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0xbe); tml = Read_DS18B20(); tmh = Read_DS18B20(); temp = (tmh << 8) | tml; switch(dot) { case 0: temp *=0.0625; break; case 1: temp *=0.625; break; case 2: temp *=6.25; break; } return temp; }
IIC (At24c02和Pcf8591)
两者都是IIC协议,只是两者的地址不同:一个0xa0,宁一个0x90
at24c02 void AT24C02_read_page(uchar *dat,uchar addr,uchar num) { uchar date; I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); I2CStart(); I2CSendByte(0xa1); I2CWaitAck(); while(num--) { *dat = I2CReceiveByte(); if(num) I2CSendAck(0); else I2CSendAck(1); } I2CStop(); } void AT24C02_write_page(uchar *dat,uchar addr,uchar num) { I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); while(num--) { I2CSendByte(*dat++); I2CWaitAck(); } I2CStop(); } Pf8591 void PCF8591_write(uchar date) { I2CStart(); I2CSendByte(0x90); I2CWaitAck(); I2CSendByte(0x40); I2CWaitAck(); I2CSendByte(date); I2CWaitAck(); I2CStop(); } uchar PCF8591_read(uchar channel) { uchar date; I2CStart(); I2CSendByte(0x90); I2CWaitAck(); I2CSendByte(channel); I2CWaitAck(); I2CStart(); I2CSendByte(0x91); I2CWaitAck(); date = I2CReceiveByte(); I2CSendAck(1); I2CStop(); return date; }
Ds1302
定义三个数组,分别存放写地址,读地址,和存取的时间 code uchar write_addr[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; code uchar read_addr[] ={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; uchar time[] = {0x00,0x00,0x12,0x06,0x04,0x04,0x23}; void ds1302_init() { uchar i; Write_Ds1302_Byte(0x8e,0x00); for(i=0;i<7;i++) { Write_Ds1302_Byte(write_addr[i],time[i]); } Write_Ds1302_Byte(0x8e,0x80); } void ds1302_read() { uchar i; for(i=0;i<7;i++) { time[i]=Read_Ds1302_Byte(read_addr[i]); } }
ne555
用定时器来读取 void TimerInit() { TMOD = 0x05; //方法二 TL0 = 0x00; TH0 = 0x00; TL1 = (65536 - 50000) %256; TH1 = (65536 - 50000) /256; EA = 1; ET0 = ET1 =1; TR0 = TR1 =1; } void timer1() interrupt 3 { count2++; if(count2 == 20) // 每一秒进入一次 { Fre = TL0 + TH0 *256; TL0 = 0x00; TH0 = 0x00; // 每读取一次手动重装一次 count2 = 0; } }
进阶模块 - - 一般都是国赛考
- 超声波
- 串口通讯
User
main函数
定义各种变量,参数,数组,标志位等
// main函数一般只存放这些,其他的在定时器中补充,或者在初始化中初始化 void main() { sys_init(); while(1) { key_pro(); smg_pro(); led_pro(); } }
补充
多利用如下写法,提高效率。
void led_pro() { if(led_state) return; led_state = 1; led_contral(led_buf); } void Timer1(void) interrupt 3 { if(++led_state==50) led_state=0; }
一些思维导图
void led_pro()
{
if(led_state) return;
led_state = 1;
led_contral(led_buf);
}void Timer1(void) interrupt 3 { if(++led_state==50) led_state=0; }