回头看看从找出被撑爆的内存再到最后完美搞定 DAC 的“幻灯片”平滑输出这 100 分全是我一步步啃下硬骨头、坚持不懈调试换来的main.c#include STC15F2K60S2.H #include seg.h #include chao.h #include ds18b20.h #include key.h #include led.h #include pcf8591.h #include seg.h #include init.h unsigned char seg_pos; idata unsigned char seg_buf[8]{10,10,10,10,10,10,10,10}; idata unsigned char seg_point[8]{0,0,0,0,0,0,0,0}; idata unsigned char ucled[8]{0,0,0,0,0,0,0,0}; unsigned char seg_slow_down;//100 unsigned char key_slow_down;//10 unsigned char ad_slow_down;//70 unsigned char led_slow_down;//50 unsigned char segmode; unsigned char key_val;//当前状态 unsigned char key_old;//以前的状态 unsigned char key_down; unsigned char key_up; unsigned char m,can,she; float tem; unsigned int dis; unsigned char jvcan40; unsigned char wcan30; char j0; unsigned char j_fu; unsigned int su340; idata float xia1.0; bit f2s;//s8,s9是否同时按下的标志位 unsigned int t2000ms;//s8,s9按键均处于按下状态状态持续时间是否超过2s bit jilu;//jilu1时所有按键操作无效 unsigned int t6000ms; bit start_adc; unsigned char adc_index; float v_shu; unsigned char t100ms; unsigned char t100ms_ji; bit f100ms; xdata unsigned int dis_ji[70]; // 新增这一行 extern unsigned int time_quan; // //它告诉编译器“不要重新分配内存了这个变量在别的 .c 文件里已经定义过了你直接拿来用就行”。 unsigned char j_index; unsigned char shu_index; void seg_proc() { if(seg_slow_down100)return; seg_slow_down0; temrd_temperature(); distance(); // 仅调用一次超声波函数目的是让底层更新全局变量 time_quan switch(segmode) { case 0://测距界面 seg_point[1]1; //温度数据 if(tem10) { seg_buf[0](unsigned char )tem/10%10; seg_buf[1](unsigned char )tem%10; seg_buf[2]((unsigned int )(tem*100.5))%10; } else { seg_buf[0]10; seg_buf[1](unsigned char )tem%10; seg_buf[2]((unsigned int )(tem*100.5))%10; } seg_buf[3]11; //测距数据 if(m0)//cm { seg_buf[4]10; seg_buf[5]10; seg_buf[6](dis10)?dis/10 %10:10; seg_buf[7](dis1)?dis %10:10; seg_point[5]0; seg_point[6]0; } else//m { seg_buf[4]10; seg_buf[5]0; seg_buf[6](dis10)?dis/10 %10:10; seg_buf[7](dis1)?dis %10:10; seg_point[5]1; seg_point[6]0; } break; case 1://参数界面 seg_point[1]0; seg_point[5]0; seg_point[6]0; seg_buf[0]12; seg_buf[1]can1; seg_buf[2]10; seg_buf[3]10; seg_buf[4]10; seg_buf[5]10; if(can0)//距离参数 { seg_buf[6]jvcan/10; seg_buf[7]jvcan%10; } else//温度参数 { seg_buf[6](wcan10)?wcan/10:10; seg_buf[7]wcan%10; } break; case 2://工厂模式 seg_point[1]0; seg_point[5]0; seg_buf[0]13; seg_buf[1]she1; //校准值数据 switch(she) { case 0://标准值设置界面 seg_buf[2]10; seg_buf[3]10; seg_buf[4]10; if(j0) { seg_buf[5]10; seg_buf[6](j10)?j/10 %10:10; seg_buf[7](j0)?j %10:10; } else { j_fuj*(-1); if(j_fu10) { seg_buf[5]11; seg_buf[6]j_fu/10 %10; seg_buf[7]j_fu %10; } else { seg_buf[5]10; seg_buf[6]11; seg_buf[7]j_fu %10; } } seg_point[6]0; break; case 1://介质设置界面 seg_buf[2]10; seg_buf[3]10; //传输速度 seg_buf[4](su1000)?su/1000 %10:10; seg_buf[5](su100)?su/100 %10:10; seg_buf[6](su10)?su/10 %10:10; seg_buf[7](su1)?su %10:10; seg_point[6]0; break; case 2://dac输出设置 seg_buf[2]10; seg_buf[3]10; seg_buf[4]10; seg_buf[5]10; //dac输出下限值 if(xia1)//0.1 { seg_buf[6]0; seg_buf[7](unsigned char)(xia*100.2); seg_point[6]1; } else//2.0 { seg_buf[6](unsigned char)(xia*100.2)/10; seg_buf[7](unsigned char)(xia*100.2)%10; seg_point[6]1; } break; } break; } } void key_proc() { if(key_slow_down10)return ; key_slow_down0; key_valrd_key(); key_downkey_val (key_old^key_val); key_up~key_val (key_old^key_val); if(jilu0)//不在记录状态 { if(key_val89)//s8s9均处于按下状态 { f2s1; } else { f2s0;//t2000ms不再开始计时 if(t2000ms2000)//s8,s9处于按下状态且状态持续时间超过2s { m0; jvcan40; wcan30; j0; su340; xia1.0; segmode0; t2000ms0; } } key_oldkey_val; switch(key_down) { case 4://界面按键 if(segmode3)segmode0; if(segmode0)//每次重新进入测距界面 { m0; } if(segmode1)//每次从测距界面切换到参数界面 { can0; } if(segmode2) { she0; } break; case 5: switch(segmode) { case 0://在测距界面下 m^1;//切换距离显示单位 break; case 1://在参数界面下 can^1; break; case 2://在工厂模式下 if(she3)she0; break; } break; case 8://加 if(segmode1can0)//在距离参数界面下 { jvcan10; if(jvcan92)jvcan10; } if(segmode1can1)//在温度参数界面下 { if(wcan81)wcan0; } if(segmode2she0) { j5; if(j91)j-90; } if(segmode2she1) { su10; if(su9991)su10; } if(segmode2she2) { xia0.1; if(xia2.05)xia0.1; } if(segmode0)//在测距界面下定义为距离“记录”按键 { jilu1;//开始记录接下来6秒内距离数据的连续变化 t6000ms0;//开始计时 j_index0;//开始从0开始记录电压 } break; case 9://减 if(segmode1can0)//在距离参数界面下 { jvcan-10; if(jvcan8)jvcan90; } if(segmode1can1)//在温度参数界面下 { if(--wcan200)wcan80; } if(segmode2she0) { j-5; if(j-91)j90; } if(segmode2she1) { su-10; if(su9)su9990; } if(segmode2she2) { xia-0.1; if(xia0.09)xia2.0; } if(segmode0)//在测距界面下定义为“输出”按键 { if(jilu0)//设备已完成数据记录 { start_adc1;//开始让dac把dis_ji[]里的数据像放幻灯片一样一张张播出来 adc_index0; } } break; } } } void led_proc() { unsigned char i; if(led_slow_down50)return ; led_slow_down0; //校准测距结果 dis(unsigned int)((su*100)*((time_quan/1000000.0)/2.0)j);//没按S8前只测距不输出DAC //led指示灯 if(segmode0)//测距界面 { if(dis255) { for(i0;i8;i) { ucled[i]1; } } else { for(i0;i8;i) { if((dis(0x01i))!0) ucled[i]1; else ucled[i]0; } } } if(segmode1)//参数界面 { ucled[7]1; ucled[0]ucled[1]ucled[2]ucled[3]ucled[4]ucled[5]ucled[6]0; } if(segmode2)//工厂界面 { ucled[0](f100ms1)?1:0; ucled[7]ucled[1]ucled[2]ucled[3]ucled[4]ucled[5]ucled[6]0; } //继电器控制 if((disjvcan-5)(disjvcan5)(temwcan))relay(1); else relay(0); } void ad_proc() { unsigned int dis_val;//用于输出dis_ji[]里的数据 if(ad_slow_down70)return ; ad_slow_down0; if(start_adc1)//开始输出adc { if(adc_index60)//电压没有输完 { dis_valdis_ji[adc_index];//一个一个数据接着来 //DAC输出功能 if(dis_val10) { v_shuxia; } else if(dis_val10dis_val90) { v_shu((5.0-xia)/80.0)*(dis_val-90.0)5.0; } else { v_shu5.0; } da_zhuanhuan(v_shu*51.0); adc_index;//切换到下一个数据 } else//说明已经全部输出完了 { adc_index0;//从0开始输出电压 start_adc0;//停止输出adc } } } void servicet1() interrupt 3 { seg_slow_down; ad_slow_down; key_slow_down; led_slow_down; if(seg_pos8)seg_pos0; seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]); led_disp(ucled); //判断s8s9同时按下有没有超过2s if(f2s1) { if(t2000ms3000) { t2000ms; } } if(jilu1)//开始记录接下来6s内距离数据的连续变化 { if(t6000ms6000) { t6000ms0; jilu0;//数据记录完成 } if(t100ms_ji100)//把6000ms分成60分 { t100ms_ji0; dis_ji[j_index]dis;//把数据存进了 dis_ji 数组里 j_index; } } if(t100ms100) { t100ms0; f100ms^1; } } void main() { Delay750ms(); rd_temperature(); sys_init(); Timer1_Init(); while(1) { seg_proc(); key_proc(); led_proc(); ad_proc(); } }seg.c#include seg.h unsigned char code seg_wei[]{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; unsigned char code seg_duan[]{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff, 0xbf,0x8c,0x8e}; //11---,12--P,13--F void seg_disp(unsigned char wei,duan,point) { P00XFF; P2P20X1F|0XE0; P20X1F; P0seg_wei[wei]; P2P20X1F|0Xc0; P20X1F; P0seg_duan[duan]; if(point1)P00x7f; P2P20X1F|0XE0; P20X1F; }init.c#include init.h void sys_init(void) { P00xff; P2P20X1F|0X80; P20X1F; P00x00; P2P20X1F|0Xa0; P20X1F; } void Delay750ms(void) //12.000MHz { unsigned char data i, j, k; _nop_(); _nop_(); i 35; j 51; k 182; do { do { while (--k); } while (--j); } while (--i); } void Timer1_Init(void) //1毫秒12.000MHz { AUXR 0xBF; //定时器时钟12T模式 TMOD 0x0F; //设置定时器模式 TL1 0x18; //设置定时初始值 TH1 0xFC; //设置定时初始值 TF1 0; //清除TF1标志 TR1 1; //定时器1开始计时 ET11; EA1; }led.c#include led.h static unsigned char temp_l0x00; static unsigned char temp_old_l0xff; void led_disp(unsigned char *ucled) { temp_l0x00; temp_l(ucled[0]0)|(ucled[1]1)| (ucled[2]2)|(ucled[3]3)| (ucled[4]4)|(ucled[5]5)| (ucled[6]6)|(ucled[7]7); if(temp_l!temp_old_l) { P0~temp_l; P2P20X1F|0X80; P20X1F; temp_old_ltemp_l; } } static unsigned char temp_30x00; static unsigned char temp_old_30xff; void relay(bit enable) { if(enable1) { temp_3|0x10; } else temp_3 ~0x10; if(temp_3!temp_old_3) { EA0; P0temp_3; P2P20X1F|0Xa0; P20X1F; temp_old_3temp_3; EA1; } }pcf8591.c#include pcf8591.h /* # I2C浠爜鐗囨璇存槑 1. 鏈枃浠跺す涓彁渚涚殑椹卞姩浠爜渚涘弬璧涢€夋墜瀹屾垚绋嬪簭璁捐鍙傝€冦€? 2. 鍙傝禌閫夋墜鍙互鑷缂栧啓鐩稿叧浠爜鎴栦互璇ヤ唬鐮佷负鍩虹锛屾牴鎹墍閫夊崟鐗囨満绫诲瀷銆佽繍琛岄€熷害鍜岃瘯棰? 涓鍗曠墖鏈烘椂閽熼鐜囩殑瑕佹眰锛岃繘琛屼唬鐮佽皟璇曞拰淇敼銆? */ sbit sclP2^0; sbit sdaP2^1; #define DELAY_TIME 1 // static void I2C_Delay(unsigned char n) { do { _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); } while(n--); } // void I2CStart(void) { sda 1; scl 1; I2C_Delay(DELAY_TIME); sda 0; I2C_Delay(DELAY_TIME); scl 0; } // void I2CStop(void) { sda 0; scl 1; I2C_Delay(DELAY_TIME); sda 1; I2C_Delay(DELAY_TIME); } // void I2CSendByte(unsigned char byt) { unsigned char i; for(i0; i8; i){ scl 0; I2C_Delay(DELAY_TIME); if(byt 0x80){ sda 1; } else{ sda 0; } I2C_Delay(DELAY_TIME); scl 1; byt 1; I2C_Delay(DELAY_TIME); } scl 0; } //// //unsigned char I2CReceiveByte(void) //{ // unsigned char da; // unsigned char i; // for(i0;i8;i){ // scl 1; // I2C_Delay(DELAY_TIME); // da 1; // if(sda) // da | 0x01; // scl 0; // I2C_Delay(DELAY_TIME); // } // return da; //} // unsigned char I2CWaitAck(void) { unsigned char ackbit; scl 1; I2C_Delay(DELAY_TIME); ackbit sda; scl 0; I2C_Delay(DELAY_TIME); return ackbit; } //// //void I2CSendAck(unsigned char ackbit) //{ // scl 0; // sda ackbit; // I2C_Delay(DELAY_TIME); // scl 1; // I2C_Delay(DELAY_TIME); // scl 0; // sda 1; // I2C_Delay(DELAY_TIME); //} //unsigned char ad_zhuanhuan(unsigned char addr)//读 //{ // unsigned char temp; // EA0; // //start // I2CStart(); // // //写芯片地址 // I2CSendByte(0x90); // I2CWaitAck(); // //写选择通道 // I2CSendByte(addr); // I2CWaitAck(); // // // //start // I2CStart(); // //写芯片地址 // I2CSendByte(0x91); // I2CWaitAck(); // // // //保存数据 // tempI2CReceiveByte(); // //发送ack1 // I2CSendAck(1); // //stop // I2CStop(); // // EA1; // return temp; // //} void da_zhuanhuan(unsigned char dat)//写 { EA0; //start I2CStart(); //写芯片地址 I2CSendByte(0x90); I2CWaitAck(); //写选择通道 I2CSendByte(0x41); I2CWaitAck(); //写数据 I2CSendByte(dat); I2CWaitAck(); //stop I2CStop(); EA1; } //void ee_write(unsigned char *str,unsigned char addr,unsigned char num) //{ // EA0; // //start // I2CStart(); // // // //写芯片地址 // I2CSendByte(0xa0); // I2CWaitAck(); // //写选择通道 // I2CSendByte(addr); // I2CWaitAck(); // // //写数据 // while(num--) // { // I2CSendByte(*str); // I2CWaitAck(); // I2C_Delay(200); // } // // //stop // I2CStop(); // EA1; // // I2C_Delay(255); // I2C_Delay(255); // I2C_Delay(255); // I2C_Delay(255); //} //void ee_read(unsigned char *str,unsigned char addr,unsigned char num) //{ // EA0; // //start // I2CStart(); // // // //写芯片地址 // I2CSendByte(0xa0); // I2CWaitAck(); // //写选择通道 // I2CSendByte(addr); // I2CWaitAck(); // // // //start // I2CStart(); // //写芯片地址 // I2CSendByte(0xa1); // I2CWaitAck(); // // // //保存数据 // while(num--) // { // *strI2CReceiveByte(); // if(num)I2CSendAck(0); // else I2CSendAck(1); // } // // //stop // I2CStop(); // EA1; //}key.c#include key.h unsigned char rd_key(void) { unsigned char temp0; AUXR~0X10; P440;P421;P351;P341; if(P300)temp7; if(P310)temp6; if(P320)temp5; if(P330)temp4; P441;P420;P351;P341; if(P300)temp11; if(P310)temp10; if(P320)temp9; if(P330)temp8; if(P330P320)temp89; P441;P421;P350;P341; if(P300)temp15; if(P310)temp14; if(P320)temp13; if(P330)temp12; AUXR |0X10; return temp; }chao.c#include chao.h sbit TXP1^0; sbit RXP1^1; // 在文件头部定义一个全局变量 unsigned int time_quan; void Delay12us(void) //12.000MHz { unsigned char data i; _nop_(); _nop_(); i 38; while (--i); } void wave_init(void) { unsigned char i; EA0; for(i0;i8;i) { TX1; Delay12us(); TX0; Delay12us(); } EA1; } unsigned int distance(void) { unsigned int time; CHCL0; CMOD0X00; wave_init(); CR1; while((RX1)(CF0)); CR0; if(CF0) { time(CH8)|CL; time_quantime; return (time*0.017); } else//超时没收到 { CF0; time_quan0; return 0; } }ds18b20.c#include ds18b20.h sbit DQP1^4; /* # 鍗曟€荤嚎浠爜鐗囨璇存槑 1. 鏈枃浠跺す涓彁渚涚殑椹卞姩浠爜渚涘弬璧涢€夋墜瀹屾垚绋嬪簭璁捐鍙傝€冦€? 2. 鍙傝禌閫夋墜鍙互鑷缂栧啓鐩稿叧浠爜鎴栦互璇ヤ唬鐮佷负鍩虹锛屾牴鎹墍閫夊崟鐗囨満绫诲瀷銆佽繍琛岄€熷害鍜岃瘯棰? 涓鍗曠墖鏈烘椂閽熼鐜囩殑瑕佹眰锛岃繘琛屼唬鐮佽皟璇曞拰淇敼銆? */ // void Delay_OneWire(unsigned int t) { unsigned char i; while(t--){ for(i0;i12;i); } } // void Write_DS18B20(unsigned char dat) { unsigned char i; for(i0;i8;i) { DQ 0; DQ dat0x01; Delay_OneWire(5); DQ 1; dat 1; } Delay_OneWire(5); } // unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i0;i8;i) { DQ 0; dat 1; DQ 1; if(DQ) { dat | 0x80; } Delay_OneWire(5); } return dat; } // 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; } float rd_temperature(void) { unsigned char low,high; EA0;init_ds18b20();EA1; EA0;Write_DS18B20(0xcc);EA1; EA0;Write_DS18B20(0xbe);EA1; EA0;lowRead_DS18B20();EA1; EA0;highRead_DS18B20();EA1; EA0;init_ds18b20();EA1; EA0;Write_DS18B20(0xcc);EA1; EA0;Write_DS18B20(0x44);EA1; return ((float)(high8|low))*0.0625; }