蓝桥杯单片机代码模板

    科技2024-03-31  109

    蓝桥杯单片机代码 看会就觉得很简单 前言 此博客为蓝桥杯自写基本代码 官方在比赛时会提高 DS18B20 1320 IIC的部分代码稍微改写或补充即可; 关于IIC协议部分的代码 可由元件数据表查找可得。

    程序代码如下

    main.c函数include.h函数ENABLE138函数h文件c文件 数码管h文件C文件 矩阵键盘H文件C文件 IIC协议H文件C文件 DS1302H文件C文件 DS18B20H文件C文件 PCF8591H文件C文件 AT24C02H文件C文件 串口H文件C文件

    main.c函数

    #include "include.h" u16 timer = 0; u8 led = 0xff; u8 nkey; void Timer2Init(void) //2ms@12.000MHz { AUXR |= 0x04; //定时器时钟1T模式 T2L = 0x40; //设置定时初值 T2H = 0xA2; //设置定时初值 AUXR |= 0x10; //定时器2开始计时 IE2 |= (1<<2); //允许T2中断 EA=1;//中断总开关 } //系统初始化 void allint() { P0 = 0xff; enable(LED); P0 = 0x00; enable(ULN); P0 = 0x00; enable(WEI); P0 = 0xff; enable(DUAN); } //LED控制 改变led变量即可 void led_run() { P0 = led; enable(LED); } //主函数 void main() { Timer2Init(); allint(); while(1) { nkey = jp_buff();//键值判断 if (nkey != 0)//存在按键 nkey不等于0 { jp_choose(nkey);//键值选择 } } } //中断部分 自由添加代码 void T2_int() interrupt 12//2ms { smg_display();//数码管显示函数 led_run();//led点灯函数 if(timer++ == 500) //1s操作 { timer = 0; } }

    include.h函数

    #ifndef _INCLUDE_H_ //建立库函数格式 #define _INCLUDE_H_ //建立库函数格式 #define u16 unsigned int #define u8 unsigned char #define LED 4 //LED #define ULN 5 //外接 #define WEI 6 // 位选端 #define DUAN 7 // 段选端 //调用自编写函数库 #include <STC15F2K60S2.H> #include <intrins.h> #include "smg.h" #include "jp.h" #include "iic.h" #include "ds1302.h" #include "enable138.h" #include "onewire.h" #include "pcf8591.h" #include "at24c02.h" #include "uart.h" #endif //建立库函数格式

    ENABLE138函数

    h文件

    #ifndef _ENABLE138_H_ #define _ENABLE138_H_ #include "include.h" void enable(u8 x); #endif

    c文件

    #include "enable138.h" void enable(u8 x) { P2&= 0x1f; //使高三位为0 P2|=(x << 5); //判断输入X的值 选择使能口 _nop_(); //等待反应 _nop_(); //等待反应 P2&= 0x1f; //恢复初始状态 }

    数码管

    h文件

    #ifndef _SMG_H_ #define _SMG_H_ #include "include.h" void buff_change(u16 d1,d2,d3,d4,d5,d6,d7,d8); void smg_display(); void smg_flash_services(); extern u8 displaydat[8]; extern u8 smg_flashset; #endif

    C文件

    #include "smg.h" u8 smg_flashset=0x00;bit0¶ÔÓÃÓÒ1 u16 smg_flashT=200; u8 code smgDU[34] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E, // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E, // 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. A. B. C. D. E. F. 0xff,0xbf}; // Ãð - u8 smgWE[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位选口 static u16 num =0; u16 smgbuff[8]; //数码管显示数据更换 void buff_change(u16 d1,d2,d3,d4,d5,d6,d7,d8) { smgbuff[0] = d1; smgbuff[1] = d2; smgbuff[2] = d3; smgbuff[3] = d4; smgbuff[4] = d5; smgbuff[5] = d6; smgbuff[6] = d7; smgbuff[7] = d8; } //数码管闪烁 (smg_flashset控制位置) void smg_flash_services() //2ms进一次 { static u16 flashcount=0; u8 i=0; flashcount++; if(flashcount<smg_flashT/2) //在闪烁周期前半段 保持熄灭 { for(i=0;i<8;i++) { if(smg_flashset&(0x80>>i)) //闪烁 (灭) smgWE[i]=0x00; else //闪烁(亮) smgWE[i]=(0x01<<i); } } else if(flashcount<smg_flashT) //后半段 褒词点亮 { for(i=0;i<8;i++) smgWE[i]=(0x01<<i); } else flashcount=0; } void smg_display() { P0 = 0xff; enable(DUAN); P0 = smgWE[num]; enable(WEI); P0 = smgDU[smgbuff[num]]; enable(DUAN); num++; num &= 7; }

    矩阵键盘

    H文件

    #ifndef _JP_H_ #define _JP_H_ #include "include.h" void jp_choose(u8 keys); u8 jp_buff(); extern u8 KEY_UP; #endif

    C文件

    #include "jp.h" u8 KEY_UP=1; //松键标志 void Delay7ms() //@12.000MHz { unsigned char i, j; i = 82; j = 179; do { while (--j); } while (--i); } //键值选择 (后续内容在对应按键下进行填写) void jp_choose(u8 keys) { switch(keys) { case 1: //s7 break; case 2: //s11 break; case 3: //s15 break; case 4: //s19 break; case 5: //s6 break; case 6: //s10 break; case 7: //s14 break; case 8: //s18 break; case 9: //s5 break; case 10: //s9 break; case 11: //s13 break; case 12: //s17 break; case 13: //s4 break; case 14: //s8 break; case 15: //s12 break; case 16: //s16 break; default: break; } } //矩阵键盘按键位置判断 u8 jp_buff() { u8 keyvalue= 0;//1~16 u8 cache=0; u8 Hang=0; u8 Lie=0; P3&=0xc0;//bit5 bit4复位 P3|=0x0f;//bit3~bit0置位 P42=0; P44=0; if(((P3&0x0f)!=0x0f)&&(KEY_UP)) { Delay7ms(); P3&=0xc0; P3|=0x0f; P42=0; P44=0; if(((P3&0x0f)!=0x0f)&&(KEY_UP)) { KEY_UP=0; cache=P3&0x0f;//把行口状态取过来保存到caache低四位 switch(cache) { case 0x0e:Hang=1; break; case 0x0d:Hang=2; break; case 0x0b:Hang=3; break; case 0x07:Hang=4; break; } P3&=0xf0; P3|=0x30; P42=1; P44=1; if(P44==0) Lie=1; else if(P42==0) Lie=2; else if(P35==0) Lie=3; else if(P34==0) Lie=4; keyvalue=Hang*4+Lie - 4; } } P3&=0xc0;//bit5 4复位 P3|=0x0f;//bit3~bit0置位 P42=0; P44=0; if(((P3&0x0f)==0x0f)&&(!KEY_UP)) { KEY_UP=1; } return keyvalue; }

    IIC协议

    比赛会专门给 稍微改一下头文件即可

    H文件

    #ifndef _IIC_H #define _IIC_H #include "include.h" 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); #endif

    C文件

    #include "iic.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; } 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; } 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; }

    DS1302

    时钟芯片(秒、分、时、日、月、周、年) 此次只写了 秒分时的 后面的修改R/W的地址即可 同时 只有最后两个函数自写 其他官方均写好了 如有不懂,看芯片手册即可找到地址。

    H文件

    #ifndef __DS1302_H #define __DS1302_H #include "include.h" void Write_Ds1302(unsigned char temp); void Write_Ds1302_Byte( unsigned char address,unsigned char dat ); unsigned char Read_Ds1302_Byte( unsigned char address ); void Set_RTC(u8 *pucrtc); void Read_RTC(u8 *pucrtc); #endif

    C文件

    #include <ds1302.h> sbit SCK=P1^7; sbit SDA=P2^3; sbit RST = P1^3; // DS1302¸´Î» void Write_Ds1302(unsigned char temp) { unsigned char i; for (i=0;i<8;i++) { SCK=0; SDA=temp&0x01; temp>>=1; SCK=1; } } void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) { RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST=0; } unsigned char Read_Ds1302_Byte ( unsigned char address ) { unsigned char i,temp=0x00; RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302(address); for (i=0;i<8;i++) { SCK=0; temp>>=1; if(SDA) temp|=0x80; SCK=1; } RST=0; _nop_(); SCK=0; _nop_(); SCK=1; _nop_(); SDA=0; _nop_(); SDA=1; _nop_(); return (temp); } //设置时钟 void Set_RTC(u8 *pucrtc) { u8 temp; Write_Ds1302_Byte(0x8e,0); //wp = 0,允许写操作 temp = ((pucrtc[0]/10)<<4)+pucrtc[0]%10; Write_Ds1302_Byte(0x84,temp); //设置时 temp = ((pucrtc[1]/10)<<4)+pucrtc[1]%10; Write_Ds1302_Byte(0x82,temp); //设置分 temp = ((pucrtc[2]/10)<<4)+pucrtc[2]%10; Write_Ds1302_Byte(0x80,temp); //设置秒 Write_Ds1302_Byte(0x8e,0x80); //wp=1,禁止写操作 } //读取时钟 void Read_RTC(u8 *pucrtc) { u8 temp; temp = Read_Ds1302_Byte(0x85); //读取时 pucrtc[0] = (temp>>4)*10+(temp&0xf); temp = Read_Ds1302_Byte(0x83); //读取分 pucrtc[1] = (temp>>4)*10+(temp&0xf); temp = Read_Ds1302_Byte(0x81); //读取秒 pucrtc[2] = (temp>>4)*10+(temp&0xf); }

    DS18B20

    温度传感器 由于我用的12T的 在官方给的文件延时部分加了一个12的for循环

    H文件

    #ifndef __ONEWIRE_H #define __ONEWIRE_H #include "include.h" unsigned char rd_temperature(void); u16 DS18B20_read(); #endif

    C文件

    #include "onewire.h" sbit DQ = P1^4; //单总线接口 //延时 void Delay_OneWire(unsigned int t) //STC89C52RC { u16 num = 0;// while(t--) for(num = 0;num <= 12;num++); //12T } //通过单总线向DS18B20写一个字节 void Write_DS18B20(unsigned char dat) { unsigned char i; for(i=0;i<8;i++) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5); } //´ÓDS18B20读取一个字节 unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i=0;i<8;i++) { DQ = 0; dat >>= 1; DQ = 1; if(DQ) { dat |= 0x80; } Delay_OneWire(5); } return dat; } //DS18B20初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0; Delay_OneWire(80); DQ = 1; Delay_OneWire(10); initflag = DQ; Delay_OneWire(5); return initflag; } //读取温度 u16 DS18B20_read() { u16 high,low,date; init_ds18b20(); //初始化 Write_DS18B20(0xcc);//º忽略地址 跳过ROM Write_DS18B20(0x44);//启动温度转换 init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0xbe);// 读暂存器 low = Read_DS18B20(); // 低 high = Read_DS18B20(); // 高 date = high << 4; date |= (low >>4); return date; }

    PCF8591

    数模采集

    H文件

    #ifndef _PCF8591_H_ #define _PCF8591_H_ #include "include.h" u8 PCF8591_ADC(u8 ch); void PCF8591_DAC(u8 dat); #endif

    C文件

    EA在函数中 防止中断打扰,故暂时关闭

    #include "pcf8591.h" //DA void PCF8591_DAC(u8 dat) { EA = 0; IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(0x40); IIC_WaitAck(); IIC_SendByte(dat); IIC_WaitAck(); IIC_Stop(); EA = 1; } //AD u8 PCF8591_ADC(u8 ch) { u8 dat = 0; EA = 0; IIC_Start(); //初始化 IIC_SendByte(0x90); //写入 IIC_WaitAck(); //等待应答 IIC_SendByte(0x40|ch); //写入模拟电压 IIC_WaitAck(); //等待应答 IIC_Stop(); //等待应答 IIC_Start(); //初始化 IIC_SendByte(0x91); //写入 IIC_WaitAck(); //等待应答 dat = IIC_RecByte(); //读返回数据 IIC_SendAck(1); //给予NO ASK EA = 1; return dat; }

    AT24C02

    H文件

    #ifndef _AT24C02_H_ #define _AT24C02_H_ #include "include.h" void at24c02_write(u8 add, u8 dat); u8 at24c02_read(u8 add); void at24c02_writestr(u8 start,u8 *pbuff, u8 num); void at24c02_readstr(u8 start, u8 *pbuff, u8 num); #endif

    C文件

    #include "at24c02.h" void Delay5ms() //@12.000MHz { unsigned char i, j; i = 59; j = 90; do { while (--j); } while (--i); } //单一写入 void at24c02_write(u8 add, u8 dat) //add为地址 dat为数据 { EA = 0; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); //写入要写入的地址 IIC_WaitAck(); IIC_SendByte(dat); //写入要写入的密码 IIC_WaitAck(); IIC_Stop(); EA = 1; Delay5ms(); //手册写明 写入数据是 要有 5ms延时 } //单一读入 u8 at24c02_read(u8 add) //add 地址 { u8 dat; EA = 0; IIC_Start(); IIC_SendByte(0xa0); //开启端口 IIC_WaitAck(); IIC_SendByte(add); //发送要的读的地址 IIC_WaitAck(); IIC_Start(); IIC_SendByte(0xa1); // 发送读要求 IIC_WaitAck(); dat = IIC_RecByte(); //接收读内容 IIC_SendAck(1); //返回NO ASK EA = 1; return dat; } //写入多个 (数组指针) void at24c02_writestr(u8 start,u8 *pbuff, u8 num) //位置,数组,数量 { while(num) { at24c02_write(start,*pbuff); start++; pbuff++; num--; } } //读取多个 (数组指针) void at24c02_readstr(u8 start, u8 *pbuff, u8 num) { while(num) { *pbuff = at24c02_read(start); start++; pbuff++; num--; } }

    串口

    H文件

    #ifndef _UART_H_ #define _UART_H_ #include "include.h" void uart1_init(u16 BAUD); void senddata(u8 dat); void sendstr(u8 *s); void clearuart1receive(); extern u8 uart1receive[7]; #endif

    C文件

    #include "uart.h" #define FOSC 12000000L //系统频率 bit busy; //设置忙标志位 u8 uart1receive[7] = {0}; //收大小 u8 uart1receive_p =0; //详细参考手册 void uart1_init(u16 BAUD) // 输入对应的波特率 { SCON = 0x50; //无校验 AUXR |= 0x40;//0100 0000 只对AUXR的bit6进行置位 只把T1加倍12 AUXR &= 0xfe;//1111 1110 相当于把bit0复位 作用时把T1作为串1波特率发生器 TMOD &= 0x0f;//T1 模式0 16位重装 GTAE c/t M1 M0 GTAE c/t M1 M0 TL1 = (65536 - (FOSC/4/BAUD)); TH1 = (65536 - (FOSC/4/BAUD))>>8;// TR1 =1; ES =1; EA =1; } void uart() interrupt 4 { if (RI) { RI =0; uart1receive[uart1receive_p] = SBUF; uart1receive_p++; } if (TI) { TI =0; busy =0; } } //发生一数据 void senddata(u8 dat) { while(busy); //判断 busy= 1; SBUF = dat; } //发送字符串 void sendstr(u8 *s) { while(*s) { senddata(*s++); } } //清除数据 void clearuart1receive() { u8 i = 0; for(i=0;i<7;i++) //根据数组大小来改变for循环 { uart1receive[i] =0; } uart1receive_p =0; }
    Processed: 0.015, SQL: 8