1、基础#include STC15F2K60S2.H #define uchar unsigned char #define uint unsigned int #define Y0 P2(P20x1f) #define Y4 P2(P20x1f)|0x80//LED #define Y5 P2(P20x1f)|0xa0//继电器 #define Y6 P2(P20x1f)|0xc0//smg #define Y7 P2(P20x1f)|0xe0//smg2、初始化void Init_sys() { Y0;P00xff;Y4;//关灯 Y0;P00x00;Y5;//关器继电器、蜂鸣器 Y0; }3、点灯int main() { Y0;Y4;P00xff;P070;Y0; } 给0灯亮给1灯灭 P00对应灯L1P01对应L2同理P07对应灯L84、蜂鸣器int main() { Y0;P00x00;Y5;Y0;//关闭所有器件 } int main() { Y0;P041;Y5;Y0;//开继电器 } int main() { Y0;P061;Y5;Y0;//开蜂鸣器 }5、定时器5.0定时器0待写5.1定时器1频率依据题目选定无串口一般选12MHz定时长度数码管一般选2~3ms定时器0/1模式具有16位自动重装载内部资源定时器时钟12Tvoid Timer1Init(void) //1毫秒12.000MHz { AUXR 0xBF; //定时器时钟12T模式 TMOD 0x0F; //设置定时器模式 TL1 0x18; //设置定时初始值 TH1 0xFC; //设置定时初始值 TF1 0; //清除TF1标志 TR1 1; //定时器1开始计时 } int main() { Timer1Init(); ET11;//打开定时器1的中断 EA1; } void T1_int()interrupt 3 { static uint t0; t; if(t100) { t0;Y0;P0~P0;Y4;Y0; } }5.2定时器2首先STC15F2K60S2是有定时器2的且掌握定时器的使用的必须的同样stc助手是可以生成配置文件的void Timer2Init(void) //2毫秒12.000MHz { AUXR 0xFB; //定时器时钟12T模式 T2L 0x30; //设置定时初始值 T2H 0xF8; //设置定时初始值 AUXR | 0x10; //定时器2开始计时 }IE2|0x04;EA1;是必须的为什么不直接ET21定时器2中断允许位因为ET2没有单独的寄存器它被包括在IE2的第2位定时器2只有16位自动重装载模式故中断服务函数不再重写赋值void main() { Timer2Init(); IE2|0x04;EA1; while(1); } void T2_inter()interrupt 12 //注意这里是12 { smg(buff,0); }6、数码管注共阳数码管定时器也可以2-3ms扫描节约芯片资源static uchar digit[]{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0XFF}; //point1代表某位加小数点如下为第六位显示温度36.7 void smg(uchar *buff,uchar point) { static uchar i0; Y0;P00xff;Y7; Y0;P01i;Y6; Y0;P0digit[buff[i]]; if(point1i6) P00x80; Y7; if(i8) i0; } /*---------------------------*/ uchar buff[8] {8,9,10,0,1,2,3,4}; void main() { } void T1_int()interrupt 3 { smg(buff,1);//1ms不断扫描 }7、PWM脉宽调制争议其中TL寄存器部分是65535还是65536是255还是256初学者容易在次产生争议答65536256已使用示波器测量确定的读者亦可自行推导以下代码测得P20输出频率为100Hz占空比为2%void Timer0Init(void) //12.000MHz { AUXR 0x7F; //定时器时钟12T模式 TMOD 0xF0; //设置定时器模式 TL0 (65536-100)%256; //设置定时初始值 TH0 (65536-100)/256; //设置定时初始值 TF0 0; //清除TF0标志 TR0 1; //定时器0开始计时 } void Time0()interrupt 1 { static uchar t0; t; if(t98) P200; else if(t100) {P201;t0;} }8、温度DS18B20注1、延时函数 *102、2次 init_ds18b20();3、直接读取 不延时4、先读 低位 再 高位5、小数点是 / 166、温度*10的时候一定要用unsigned int ,若是uchar最大255温度超过30°不行7、H(H8)|L;有括号//1、第一步改写温度延时函数 void Delay_OneWire(unsigned int t) { t*10; while(t--); } //2、写获取温度函数 float rd_temperature(void) { unsigned int H,L; init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0x44);Delay_OneWire(50); init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0xbe); LRead_DS18B20(); HRead_DS18B20(); H(H8)|L; return H/16.0; } //依据题目定义为float float wendu0; //一种更好的写法 int Get_wendu() { unsigned int H,L; init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0xbe); LRead_DS18B20();HRead_DS18B20(); init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0x44); H(H8)|L; return H/16.0*10; }9、实时时钟DS13021、Write_Ds1302_Byte(0x8e,0xff);而不是12、一定是循环7次而不是8次否则导致错误}void ds1302_config(uchar*t) { uchar addr_W0x80,i; Write_Ds1302_Byte(0x8e,0x00);// for(i0;i7;i) { Write_Ds1302_Byte(addr_W,t[i]); addr_W2; } Write_Ds1302_Byte(0x8e,0xff); } void ds1302_read(uchar*t) { uchar addr_W0x81,i; for(i0;i7;i) { t[i]Read_Ds1302_Byte(addr_W); addr_W2; t[i]t[i]/16*10t[i]%16; } } //////////////伪代码 uchar time[7]{0x55,0x27,0x16,0x07,0x04,0x05,0x23};//年星期月日时分秒 //数组最后是年第一个是秒 void main() { ds1302_config(time); while(1) { ds1302_read(time); buff[0]time[2]/10;buff[1]time[2]%10; buff[3]time[1]/10;buff[4]time[1]%10; buff[6]time[0]/10;buff[7]time[0]%10; }10、串口10.1只发送由于只发送故不用开启串口中断涉及寄存器ESEA可不管1、STC-ISP配置如下2、代码如下void UartInit(void) //9600bps11.0592MHz { SCON 0x50; //8位数据,可变波特率 AUXR 0xBF; //定时器时钟12T模式 AUXR 0xFE; //串口1选择定时器1为波特率发生器 TMOD 0x0F; //设置定时器模式 TL1 0xE8; //设置定时初始值 TH1 0xFF; //设置定时初始值 ET1 0; //禁止定时器%d中断 TR1 1; //定时器1开始计时 } //发送函数1字节 void usart_send(unsigned char t) { SBUFt; while(TI0);TI0; } //发送字符串 void Send_buff(uchar *dat) { while(*dat ! \0) Send_Usart(*dat); } //实例代码 void main() { UartInit(); while(1) { usart_send(0x0f); Delay100ms(); } }deepseek写的简化代码void UART_SendString(unsigned char *str) { while(*str ! \0) // 遍历字符串直到结束符 { SBUF *str; // 发送当前字符并指针自增 while(!TI); // 等待发送完成(TI1) TI 0; // 必须清除发送完成标志 } }10.2接收与发送void UartInit(void) //9600bps11.0592MHz { SCON 0x50; //8位数据,可变波特率 AUXR 0xBF; //定时器时钟12T模式 AUXR 0xFE; //串口1选择定时器1为波特率发生器 TMOD 0x0F; //设置定时器模式 TL1 0xE8; //设置定时初始值 TH1 0xFF; //设置定时初始值 ET1 0; //禁止定时器%d中断 TR1 1; //定时器1开始计时 } void usart_send(unsigned char t) { SBUFt; while(TI0);TI0; } void main() { UartInit(); ES1;EA1; while(1) { } } void jieshou_usart() interrupt 4 { if(RI1) { RI0; usart_send(SBUF); } }11、EEPROM掉电存储待写void write_eeprom(unsigned char add,unsigned char val) { IIC_Start(); IIC_SendByte(0xa0);//写 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(val); IIC_WaitAck(); IIC_Stop(); //写完后最好延时一下 } unsigned char read_eeprom(unsigned char add) { unsigned char da; IIC_Start(); IIC_SendByte(0xa0);//写 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); //注意这里不加停止信号 IIC_Start(); IIC_SendByte(0xa1);//读 IIC_WaitAck(); da IIC_RecByte(); IIC_SendAck(1); IIC_Stop();//省略这个停止信号影响不大官方是加了的 return da; }12、电压转换PCF8591电压读取时可以关闭中断EA0防止读数有误12.1电压读取AIN0-外部引脚 AIN1-光敏电阻 AIN2-电源接地 AIN3-滑动变阻uchar Read_adc() { uchar t; I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(3);I2CWaitAck();//这里的3是指AIN3通道 I2CStop(); I2CStart(); I2CSendByte(0x91);I2CWaitAck(); tI2CReceiveByte(); I2CSendAck(1); return t; }电压读取这个还有另一种写法参考官方例程void Init_adc() { I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(3);I2CWaitAck(); I2CStop(); } uchar getadc() { uchar t; I2CStart(); I2CSendByte(0x91);I2CWaitAck(); tI2CReceiveByte(); I2CSendAck(1); return t; } //////////---------------------------//////////////////// void main() { Init_adc(); while(1) { dianyagetadc(); buff[0]dianya/100;buff[1]dianya/10%10; buff[2]dianya%10; } }12.1电压输出void OUT_adc(uchar viot) { I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(0x40);I2CWaitAck();//0x40代表第6位为1电压输出DA转换 I2CSendByte(viot);I2CWaitAck(); I2CStop(); }13、NE555频率测量说明NE555定时器的频率测量用到P34引脚与定时器0有关。硬件操作跳线帽短接【P34】-【SIGNAL】13.1中断计数法看的小蜜蜂视频void Timer0_Init(void) // 12.000MHz { /* 定时器控制寄存器配置 */ AUXR 0x7F; // 清除AUXR寄存器的第7位(D7)选择12T模式12时钟周期1机器周期 // 12MHz时钟下1机器周期1us (12/12MHz) /* 定时器模式配置 */ TMOD 6; // 设置TMOD00000110配置定时器0为模式28位自动重装 // 模式2特点TL0计数溢出后自动从TH0重装初始值 /* 定时器初始值设置 */ TL0 0xFF; // 设置TL0初始值为0xFF255 TH0 0xFF; // 设置TH0重装值为0xFF255 // 计算公式(256 - 255) * 1us 1us中断周期 TF0 0; // 清除定时器0溢出标志(TF0)避免误触发中断 TR0 1; // 启动定时器0TR01开始计数 ET0 1; // 使能定时器0中断需配合EA1使用 // 注意此代码未设置EA总中断使能需在其他位置开启 } uint f0; uint f_t0; void main() { Timer0_Init(); EA1; while(1) { adcf_t; buff[0] adc/10000; buff[1] adc/1000%10; buff[2] adc/100%10; buff[3] adc/10%10; buff[4] adc%10; buff[5] 0; } } void Timer0_Isr(void) interrupt 1 { f; } //定时1s void Timer2_Isr(void) interrupt 12 { static uint i0; i; if(i1000) {i0;f_tf;f0;} smg(buff,0); }13.2直接读取法void Timer0_Init(void) // 定时器0初始化原注释1??12.000MHz含义不明 { AUXR 0x7F; // 使用12T模式12时钟/机器周期 TMOD 5; // 设置定时器0为模式1(0000 0101): // bit1-001: 模式116位定时器/计数器不重装载 // bit21 : C/T1配置为计数器检测P3.4/T0引脚脉冲 TL0 0x00; // 初始化计数器低字节为0从0开始计数 TH0 0x00; // 初始化计数器高字节为0 TF0 0; // 清除定时器0溢出标志 TR0 1; // 启动定时器0TR01开始计数 ET0 1; // 允许定时器0中断需配合EA1使用 } void Timer1_Init(void) // 定时器1初始化50ms12.000MHz { AUXR 0xBF; // 关闭定时器1的1T模式bit60强制使用12T模式 TMOD 0x0F; // 清零定时器1模式位高4位保持定时器0配置不变 // 问题未设置定时器1模式默认模式013位定时器 // 应改为 TMOD | 0x10; 设置为模式116位定时器 TL1 0xB0; // 设置定时初值低字节0xB0实际需根据模式计算 TH1 0x3C; // 设置定时初值高字节0x3C // 模式1下初值计算65536 - 50000 15536 → 0x3CB0 // 但模式013位最大8192会导致初值错误 TF1 0; // 清除定时器1溢出标志 TR1 1; // 启动定时器1 ET1 1; // 允许定时器1中断 } void Timer0_Isr(void) interrupt 1 // 定时器0中断服务程序未实现功能 { // 空实现未统计计数器溢出次数导致高频测量失败 } void Timer1_Isr(void) interrupt 3 { static uchar t0; t; if(t20) { ET0 0; adc(TH08)|TL0; TH00;TL00; t0; ET0 1; } }14、超声波测距1void Send_CSB() { unsigned char i; for(i0;i8;i) { TX1; Delay12us(); TX0; Delay12us(); } } void main() { TMOD0x10;//0001 0000 TH1TL10; Init_sys(); ET01;EA1; while(1) { Send_CSB();TR11;//jishi while((RX1) (TF10)); TR10; if(TF11) {TF10;distance3;} else { distanceTH1; distance((distance8)|TL1)*0.017; } TH1 0; TL1 0; Delay400ms(); buff[0]distance/100; buff[1]distance/10%10; buff[2]distance%10; } }15、按键模块15.1矩阵按键在官方例程中10ms采集一次void loop(uchar *key) { static uchar now,last; uchar t0; P421;P441; P30xff;P300; if(P340) t19; else if(P350) t15; else if(P420) t11; else if(P440) t7; P30xff;P310; if(P340) t18; else if(P350) t14; else if(P420) t10; else if(P440) t6; P30xff;P320; if(P340) t17; else if(P350) t13; else if(P420) t9; else if(P440) t5; P30xff;P330; if(P340) t16; else if(P350) t12; else if(P420) t8; else if(P440) t4; lastnow;nowt; //按下有效 // if(nowlast0) // *keynow; //松手有效 if(now0last) *keylast; }15.2长按键自写void T0_intr()interrupt 1 { unsigned char key_val 0xFF; static uchar t0; smg(buff); if(t25) { t0;nowloop(key); P30xff;P320; if(status0) { if(P340) //t17; status1; } if(status1) { if(P340) //t17; { if(press_counter20) press_counter; } else { if(press_counter5) status2; else { status0;press_counter0; } } } if(status2) { if(P341) { if(press_counter20) real1; else real2; status0; press_counter0; } } } }官方//°´¼üɨÃ躯Êý unsigned char read_key(void) { static unsigned int press_counter 0; //³¤¶Ì°´¼ü¼ÆÊýÆ÷ static unsigned char status 0; unsigned char key_val 0xFF; switch(status){ case 0: if(P33 0){ status 1; } break; case 1: if(P33 0) { if(press_counter 400) { press_counter; } } else { if(press_counter 20) { status 2; } else { status 0; //¶¶¶¯ press_counter 0; } } break; case 2: if(P33 1) { if(press_counter 400) { key_val 1; //¶Ì°´¼ü } else { key_val 2 ; //³¤°´¼ü } status 0; press_counter 0; } break; } return key_val; }
【蓝桥杯单片机】一些函数
发布时间:2026/6/4 11:50:56
1、基础#include STC15F2K60S2.H #define uchar unsigned char #define uint unsigned int #define Y0 P2(P20x1f) #define Y4 P2(P20x1f)|0x80//LED #define Y5 P2(P20x1f)|0xa0//继电器 #define Y6 P2(P20x1f)|0xc0//smg #define Y7 P2(P20x1f)|0xe0//smg2、初始化void Init_sys() { Y0;P00xff;Y4;//关灯 Y0;P00x00;Y5;//关器继电器、蜂鸣器 Y0; }3、点灯int main() { Y0;Y4;P00xff;P070;Y0; } 给0灯亮给1灯灭 P00对应灯L1P01对应L2同理P07对应灯L84、蜂鸣器int main() { Y0;P00x00;Y5;Y0;//关闭所有器件 } int main() { Y0;P041;Y5;Y0;//开继电器 } int main() { Y0;P061;Y5;Y0;//开蜂鸣器 }5、定时器5.0定时器0待写5.1定时器1频率依据题目选定无串口一般选12MHz定时长度数码管一般选2~3ms定时器0/1模式具有16位自动重装载内部资源定时器时钟12Tvoid Timer1Init(void) //1毫秒12.000MHz { AUXR 0xBF; //定时器时钟12T模式 TMOD 0x0F; //设置定时器模式 TL1 0x18; //设置定时初始值 TH1 0xFC; //设置定时初始值 TF1 0; //清除TF1标志 TR1 1; //定时器1开始计时 } int main() { Timer1Init(); ET11;//打开定时器1的中断 EA1; } void T1_int()interrupt 3 { static uint t0; t; if(t100) { t0;Y0;P0~P0;Y4;Y0; } }5.2定时器2首先STC15F2K60S2是有定时器2的且掌握定时器的使用的必须的同样stc助手是可以生成配置文件的void Timer2Init(void) //2毫秒12.000MHz { AUXR 0xFB; //定时器时钟12T模式 T2L 0x30; //设置定时初始值 T2H 0xF8; //设置定时初始值 AUXR | 0x10; //定时器2开始计时 }IE2|0x04;EA1;是必须的为什么不直接ET21定时器2中断允许位因为ET2没有单独的寄存器它被包括在IE2的第2位定时器2只有16位自动重装载模式故中断服务函数不再重写赋值void main() { Timer2Init(); IE2|0x04;EA1; while(1); } void T2_inter()interrupt 12 //注意这里是12 { smg(buff,0); }6、数码管注共阳数码管定时器也可以2-3ms扫描节约芯片资源static uchar digit[]{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0XFF}; //point1代表某位加小数点如下为第六位显示温度36.7 void smg(uchar *buff,uchar point) { static uchar i0; Y0;P00xff;Y7; Y0;P01i;Y6; Y0;P0digit[buff[i]]; if(point1i6) P00x80; Y7; if(i8) i0; } /*---------------------------*/ uchar buff[8] {8,9,10,0,1,2,3,4}; void main() { } void T1_int()interrupt 3 { smg(buff,1);//1ms不断扫描 }7、PWM脉宽调制争议其中TL寄存器部分是65535还是65536是255还是256初学者容易在次产生争议答65536256已使用示波器测量确定的读者亦可自行推导以下代码测得P20输出频率为100Hz占空比为2%void Timer0Init(void) //12.000MHz { AUXR 0x7F; //定时器时钟12T模式 TMOD 0xF0; //设置定时器模式 TL0 (65536-100)%256; //设置定时初始值 TH0 (65536-100)/256; //设置定时初始值 TF0 0; //清除TF0标志 TR0 1; //定时器0开始计时 } void Time0()interrupt 1 { static uchar t0; t; if(t98) P200; else if(t100) {P201;t0;} }8、温度DS18B20注1、延时函数 *102、2次 init_ds18b20();3、直接读取 不延时4、先读 低位 再 高位5、小数点是 / 166、温度*10的时候一定要用unsigned int ,若是uchar最大255温度超过30°不行7、H(H8)|L;有括号//1、第一步改写温度延时函数 void Delay_OneWire(unsigned int t) { t*10; while(t--); } //2、写获取温度函数 float rd_temperature(void) { unsigned int H,L; init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0x44);Delay_OneWire(50); init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0xbe); LRead_DS18B20(); HRead_DS18B20(); H(H8)|L; return H/16.0; } //依据题目定义为float float wendu0; //一种更好的写法 int Get_wendu() { unsigned int H,L; init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0xbe); LRead_DS18B20();HRead_DS18B20(); init_ds18b20(); Write_DS18B20(0xcc);Write_DS18B20(0x44); H(H8)|L; return H/16.0*10; }9、实时时钟DS13021、Write_Ds1302_Byte(0x8e,0xff);而不是12、一定是循环7次而不是8次否则导致错误}void ds1302_config(uchar*t) { uchar addr_W0x80,i; Write_Ds1302_Byte(0x8e,0x00);// for(i0;i7;i) { Write_Ds1302_Byte(addr_W,t[i]); addr_W2; } Write_Ds1302_Byte(0x8e,0xff); } void ds1302_read(uchar*t) { uchar addr_W0x81,i; for(i0;i7;i) { t[i]Read_Ds1302_Byte(addr_W); addr_W2; t[i]t[i]/16*10t[i]%16; } } //////////////伪代码 uchar time[7]{0x55,0x27,0x16,0x07,0x04,0x05,0x23};//年星期月日时分秒 //数组最后是年第一个是秒 void main() { ds1302_config(time); while(1) { ds1302_read(time); buff[0]time[2]/10;buff[1]time[2]%10; buff[3]time[1]/10;buff[4]time[1]%10; buff[6]time[0]/10;buff[7]time[0]%10; }10、串口10.1只发送由于只发送故不用开启串口中断涉及寄存器ESEA可不管1、STC-ISP配置如下2、代码如下void UartInit(void) //9600bps11.0592MHz { SCON 0x50; //8位数据,可变波特率 AUXR 0xBF; //定时器时钟12T模式 AUXR 0xFE; //串口1选择定时器1为波特率发生器 TMOD 0x0F; //设置定时器模式 TL1 0xE8; //设置定时初始值 TH1 0xFF; //设置定时初始值 ET1 0; //禁止定时器%d中断 TR1 1; //定时器1开始计时 } //发送函数1字节 void usart_send(unsigned char t) { SBUFt; while(TI0);TI0; } //发送字符串 void Send_buff(uchar *dat) { while(*dat ! \0) Send_Usart(*dat); } //实例代码 void main() { UartInit(); while(1) { usart_send(0x0f); Delay100ms(); } }deepseek写的简化代码void UART_SendString(unsigned char *str) { while(*str ! \0) // 遍历字符串直到结束符 { SBUF *str; // 发送当前字符并指针自增 while(!TI); // 等待发送完成(TI1) TI 0; // 必须清除发送完成标志 } }10.2接收与发送void UartInit(void) //9600bps11.0592MHz { SCON 0x50; //8位数据,可变波特率 AUXR 0xBF; //定时器时钟12T模式 AUXR 0xFE; //串口1选择定时器1为波特率发生器 TMOD 0x0F; //设置定时器模式 TL1 0xE8; //设置定时初始值 TH1 0xFF; //设置定时初始值 ET1 0; //禁止定时器%d中断 TR1 1; //定时器1开始计时 } void usart_send(unsigned char t) { SBUFt; while(TI0);TI0; } void main() { UartInit(); ES1;EA1; while(1) { } } void jieshou_usart() interrupt 4 { if(RI1) { RI0; usart_send(SBUF); } }11、EEPROM掉电存储待写void write_eeprom(unsigned char add,unsigned char val) { IIC_Start(); IIC_SendByte(0xa0);//写 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(val); IIC_WaitAck(); IIC_Stop(); //写完后最好延时一下 } unsigned char read_eeprom(unsigned char add) { unsigned char da; IIC_Start(); IIC_SendByte(0xa0);//写 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); //注意这里不加停止信号 IIC_Start(); IIC_SendByte(0xa1);//读 IIC_WaitAck(); da IIC_RecByte(); IIC_SendAck(1); IIC_Stop();//省略这个停止信号影响不大官方是加了的 return da; }12、电压转换PCF8591电压读取时可以关闭中断EA0防止读数有误12.1电压读取AIN0-外部引脚 AIN1-光敏电阻 AIN2-电源接地 AIN3-滑动变阻uchar Read_adc() { uchar t; I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(3);I2CWaitAck();//这里的3是指AIN3通道 I2CStop(); I2CStart(); I2CSendByte(0x91);I2CWaitAck(); tI2CReceiveByte(); I2CSendAck(1); return t; }电压读取这个还有另一种写法参考官方例程void Init_adc() { I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(3);I2CWaitAck(); I2CStop(); } uchar getadc() { uchar t; I2CStart(); I2CSendByte(0x91);I2CWaitAck(); tI2CReceiveByte(); I2CSendAck(1); return t; } //////////---------------------------//////////////////// void main() { Init_adc(); while(1) { dianyagetadc(); buff[0]dianya/100;buff[1]dianya/10%10; buff[2]dianya%10; } }12.1电压输出void OUT_adc(uchar viot) { I2CStart(); I2CSendByte(0x90);I2CWaitAck(); I2CSendByte(0x40);I2CWaitAck();//0x40代表第6位为1电压输出DA转换 I2CSendByte(viot);I2CWaitAck(); I2CStop(); }13、NE555频率测量说明NE555定时器的频率测量用到P34引脚与定时器0有关。硬件操作跳线帽短接【P34】-【SIGNAL】13.1中断计数法看的小蜜蜂视频void Timer0_Init(void) // 12.000MHz { /* 定时器控制寄存器配置 */ AUXR 0x7F; // 清除AUXR寄存器的第7位(D7)选择12T模式12时钟周期1机器周期 // 12MHz时钟下1机器周期1us (12/12MHz) /* 定时器模式配置 */ TMOD 6; // 设置TMOD00000110配置定时器0为模式28位自动重装 // 模式2特点TL0计数溢出后自动从TH0重装初始值 /* 定时器初始值设置 */ TL0 0xFF; // 设置TL0初始值为0xFF255 TH0 0xFF; // 设置TH0重装值为0xFF255 // 计算公式(256 - 255) * 1us 1us中断周期 TF0 0; // 清除定时器0溢出标志(TF0)避免误触发中断 TR0 1; // 启动定时器0TR01开始计数 ET0 1; // 使能定时器0中断需配合EA1使用 // 注意此代码未设置EA总中断使能需在其他位置开启 } uint f0; uint f_t0; void main() { Timer0_Init(); EA1; while(1) { adcf_t; buff[0] adc/10000; buff[1] adc/1000%10; buff[2] adc/100%10; buff[3] adc/10%10; buff[4] adc%10; buff[5] 0; } } void Timer0_Isr(void) interrupt 1 { f; } //定时1s void Timer2_Isr(void) interrupt 12 { static uint i0; i; if(i1000) {i0;f_tf;f0;} smg(buff,0); }13.2直接读取法void Timer0_Init(void) // 定时器0初始化原注释1??12.000MHz含义不明 { AUXR 0x7F; // 使用12T模式12时钟/机器周期 TMOD 5; // 设置定时器0为模式1(0000 0101): // bit1-001: 模式116位定时器/计数器不重装载 // bit21 : C/T1配置为计数器检测P3.4/T0引脚脉冲 TL0 0x00; // 初始化计数器低字节为0从0开始计数 TH0 0x00; // 初始化计数器高字节为0 TF0 0; // 清除定时器0溢出标志 TR0 1; // 启动定时器0TR01开始计数 ET0 1; // 允许定时器0中断需配合EA1使用 } void Timer1_Init(void) // 定时器1初始化50ms12.000MHz { AUXR 0xBF; // 关闭定时器1的1T模式bit60强制使用12T模式 TMOD 0x0F; // 清零定时器1模式位高4位保持定时器0配置不变 // 问题未设置定时器1模式默认模式013位定时器 // 应改为 TMOD | 0x10; 设置为模式116位定时器 TL1 0xB0; // 设置定时初值低字节0xB0实际需根据模式计算 TH1 0x3C; // 设置定时初值高字节0x3C // 模式1下初值计算65536 - 50000 15536 → 0x3CB0 // 但模式013位最大8192会导致初值错误 TF1 0; // 清除定时器1溢出标志 TR1 1; // 启动定时器1 ET1 1; // 允许定时器1中断 } void Timer0_Isr(void) interrupt 1 // 定时器0中断服务程序未实现功能 { // 空实现未统计计数器溢出次数导致高频测量失败 } void Timer1_Isr(void) interrupt 3 { static uchar t0; t; if(t20) { ET0 0; adc(TH08)|TL0; TH00;TL00; t0; ET0 1; } }14、超声波测距1void Send_CSB() { unsigned char i; for(i0;i8;i) { TX1; Delay12us(); TX0; Delay12us(); } } void main() { TMOD0x10;//0001 0000 TH1TL10; Init_sys(); ET01;EA1; while(1) { Send_CSB();TR11;//jishi while((RX1) (TF10)); TR10; if(TF11) {TF10;distance3;} else { distanceTH1; distance((distance8)|TL1)*0.017; } TH1 0; TL1 0; Delay400ms(); buff[0]distance/100; buff[1]distance/10%10; buff[2]distance%10; } }15、按键模块15.1矩阵按键在官方例程中10ms采集一次void loop(uchar *key) { static uchar now,last; uchar t0; P421;P441; P30xff;P300; if(P340) t19; else if(P350) t15; else if(P420) t11; else if(P440) t7; P30xff;P310; if(P340) t18; else if(P350) t14; else if(P420) t10; else if(P440) t6; P30xff;P320; if(P340) t17; else if(P350) t13; else if(P420) t9; else if(P440) t5; P30xff;P330; if(P340) t16; else if(P350) t12; else if(P420) t8; else if(P440) t4; lastnow;nowt; //按下有效 // if(nowlast0) // *keynow; //松手有效 if(now0last) *keylast; }15.2长按键自写void T0_intr()interrupt 1 { unsigned char key_val 0xFF; static uchar t0; smg(buff); if(t25) { t0;nowloop(key); P30xff;P320; if(status0) { if(P340) //t17; status1; } if(status1) { if(P340) //t17; { if(press_counter20) press_counter; } else { if(press_counter5) status2; else { status0;press_counter0; } } } if(status2) { if(P341) { if(press_counter20) real1; else real2; status0; press_counter0; } } } }官方//°´¼üɨÃ躯Êý unsigned char read_key(void) { static unsigned int press_counter 0; //³¤¶Ì°´¼ü¼ÆÊýÆ÷ static unsigned char status 0; unsigned char key_val 0xFF; switch(status){ case 0: if(P33 0){ status 1; } break; case 1: if(P33 0) { if(press_counter 400) { press_counter; } } else { if(press_counter 20) { status 2; } else { status 0; //¶¶¶¯ press_counter 0; } } break; case 2: if(P33 1) { if(press_counter 400) { key_val 1; //¶Ì°´¼ü } else { key_val 2 ; //³¤°´¼ü } status 0; press_counter 0; } break; } return key_val; }