0.编程心得
本题中,要求测距能达到250cm,因此pca必须配置为0x01,但直接用会死机,因此需要使用CH作为判断量。
【iic的at24c02记录】:
读设备地址:0xA1 写设备地址:0xA0
非应答信号:sda先1,后还是1。本届直接实参传1就是非应答
02表示2k大小
时序操作可完全参考手册
【onewire的ds18b20】:
MSB | LSB 的高5位全0,则读取温度为正数。全1则读取温度为负数 精度为0.0625
时序要自己背:初始化、写入0xcc、写入0x44、延时800ms、初始化、写入0xcc、写入0xbe、读取数据LSB = Read_DS18B20(); 先读出来的是低八位
MSB = Read_DS18B20();
temperature = MSB;
temperature = ( temperature << 8 ) | LSB;
temperature = (temperature >> 4)*10 + (LSB & 0x0f)*0.625;
刷新时间:2s刷新一次!!!!
数据如果闪烁,就在底层代码的读取函数中,在DQ电平变高后加一个5us
【led的刷新】:
刷新可以和数码管一起,40个50us刷新一次,2ms
涉及锁存器5的所有操作,都不要放while循环里。而且设置形参,直接调用
【iic的pcf8591记录】:
读设备地址:0x91 写设备地址:0x90
控制字:0 D/A-flag x x 0 x A/Dchannal
channal:00 外部模拟信号控制端
01 光敏电阻rd1 0x01
10 差分放大电路信号
11 滑动变阻器rb2 0x03
void dacrunning ( unsigned char value_dac ) //DAC输出,不能设置刷新位,要一直输出
{
I2CStart();
I2CSendByte( 0x90 );
I2CWaitAck();
I2CSendByte( 0x43 );
I2CWaitAck();
I2CSendByte( value_dac );
I2CWaitAck();
I2CStop();
}
输出DAC:0x43
1.比赛真题
2.特殊模块
字节反序程序
超声波程序
双按键程序
双按键下的delay函数要长一些,不然容易误判,因此人不可能做到100%同时按下
3.参考代码
main.c
#include <REGX52.H>
#include <intrins.h>
#include "iic.h"
#include "onewire.h"sfr AUXR = 0x8e;
sfr P4 = 0xc0;
sfr CCON = 0xD8; //00xx,xx00 PCA控制寄存器
sbit CF = CCON^7;
sbit CR = CCON^6;
sfr CMOD = 0xD9; //0xxx,x000 PCA 工作模式寄存器
sfr CL = 0xE9; //0000,0000 PCA计数器低字节
sfr CH = 0xF9; //0000,0000 PCA计数器高字节sbit TX = P1^0;
sbit RX = P1^1;sbit C1 = P4^4;
sbit C2 = P4^2;
sbit R3 = P3^2;
sbit R4 = P3^3;unsigned char param_mode = 1;
unsigned char SMG_mode = 1;
unsigned char param_distance = 40;
unsigned char param_temperature = 30;
unsigned char param_dac = 10;
unsigned int param_V = 340;
unsigned char save_distance = 0;
unsigned char value_led = 0xff;
float value_sonic = 0.0;
int param_calibration = 0;
bit flag_reset = 0;
bit flag_dac = 0;
bit flag_m_distance = 0;
bit flag_save_distance = 0;unsigned char code duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x8c};
unsigned char code duanma_dot[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};void scan_key ();
void value_work ();unsigned char reverse_bit ( unsigned char dat )
{dat = (dat & 0xF0) >> 4 | (dat & 0x0F) << 4;dat = (dat & 0xCC) >> 2 | (dat & 0x33) << 2;dat = (dat & 0xAA) >> 1 | (dat & 0x55) << 1;return dat;
}void select_HC573 ( unsigned char channal , unsigned char dat )
{P2 = (P2&0x1f)|0x00;P0 = dat;switch ( channal ){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)|0x00;
}void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{select_HC573 ( 6 , 0x01<<pos_SMG );select_HC573 ( 7 , value_SMG );
}void state_SMG_all ( unsigned char value_SMG )
{select_HC573 ( 6 , 0xff );select_HC573 ( 7 , value_SMG );
}void init_pca ()
{CMOD = 0x01;CCON = 0x00;
}void Delay13us() //@12.000MHz
{unsigned char i;_nop_();_nop_();i = 38;while (--i);
}bit flash_sonic = 0;
unsigned int dis_distance = 0;
void send_sonic ()
{unsigned char i;for ( i=0 ; i<8 ; i++ ){TX = 1;Delay13us();TX = 0;Delay13us();}
}void recive_sonic ()
{if ( flash_sonic == 1 ){unsigned int tmp = 0;CL = CH = CF = 0;EA = 0;send_sonic ();EA = 1;CR = 1;while ( RX==1 && CH < 0x40 );CR = 0;if ( CH > 0x40 ){CF = 0;tmp = 999;}else{tmp = CH;tmp = (tmp<<8)|CL;tmp = (unsigned int)(tmp*value_sonic+param_calibration); }dis_distance = tmp;flash_sonic = 0;if ( flag_save_distance == 1 )save_distance = tmp;}
}void Delay800ms() //@12.000MHz
{unsigned char i, j, k;_nop_();_nop_();i = 37;j = 123;k = 92;do{do{value_work();scan_key ();while (--k);} while (--j);} while (--i);
}bit flash_ds18b20 = 0;
unsigned int dis_temperature = 0;
void recive_ds18b20 ( )
{if ( flash_ds18b20 == 1 ){unsigned int tmp = 0;unsigned char MSB,LSB;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44); Delay800ms();init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);LSB = Read_DS18B20();MSB = Read_DS18B20();tmp = MSB;tmp = (tmp<<8)|LSB;
// tmp = (tmp>>4)*10+(LSB&0x0f)*0.625;tmp = (unsigned int)tmp*0.625;dis_temperature = tmp;flash_ds18b20 = 0;}
}unsigned char dac_value = 0;
void dac_work ( unsigned char dac_value )
{I2CStart();I2CSendByte(0x90);I2CWaitAck();I2CSendByte(0x43);I2CWaitAck();I2CSendByte(dac_value);I2CWaitAck();I2CStop();
}unsigned char flash_count = 0;
void flash_SMG ()
{state_SMG_all ( 0xff );if ( SMG_mode == 1 ){switch ( flash_count ){case 0:state_SMG ( 0 , duanma[dis_temperature/100] );break;case 1:state_SMG ( 1 , duanma_dot[dis_temperature/10%10] );break;case 2:state_SMG ( 2 , duanma[dis_temperature%10] );break;case 3:state_SMG ( 3 , duanma[16] );break;case 4:if ( dis_distance > 999 )state_SMG ( 4 , duanma[dis_distance/1000] );elsestate_SMG ( 4 , 0xff );break;case 5:if ( dis_distance > 99 && flag_m_distance == 0 )state_SMG ( 5 , duanma[dis_distance/100%10] );else if ( flag_m_distance == 1 )state_SMG ( 5 , duanma_dot[dis_distance/100%10] );elsestate_SMG ( 5 , 0xff );break;case 6:if ( dis_distance > 9 && flag_m_distance == 0 )state_SMG ( 6 , duanma[dis_distance/10%10] );else if ( flag_m_distance == 1 )state_SMG ( 6 , duanma[dis_distance/10%10] );elsestate_SMG ( 6 , 0xff );break;case 7:state_SMG ( 7 , duanma[dis_distance%10] );break;}}else if ( SMG_mode == 2 ){switch ( flash_count ){case 0:state_SMG ( 0 , duanma[17] );break;case 1:state_SMG ( 1 , duanma[param_mode] );break;case 2:if ( param_mode == 1 )state_SMG ( 6 , duanma[param_distance/10] );elsestate_SMG ( 6 , duanma[param_temperature/10] );break;case 3:if ( param_mode == 1 )state_SMG ( 7 , duanma[param_distance%10] );elsestate_SMG ( 7 , duanma[param_temperature%10] );break;}}else if ( SMG_mode == 3 ){switch ( flash_count ){case 0:state_SMG ( 0 , duanma[15] );break;case 1:state_SMG ( 1 , duanma[1] );break;case 2:if ( param_calibration > 99 )state_SMG ( 5 , duanma[param_calibration/100] );else if ( param_calibration < -9 )state_SMG ( 5 , duanma[16] );elsestate_SMG ( 5 , 0xff );break; case 3:if ( param_calibration > 9 )state_SMG ( 6 , duanma[param_calibration/10%10] );else if ( param_calibration < 0 && param_calibration > -9 )state_SMG ( 6 , duanma[16] );else if ( param_calibration < 9 && param_calibration != 0 )state_SMG ( 6 , duanma[(-1)*param_calibration/10%10] );elsestate_SMG ( 6 , 0xff );break; case 4:if ( param_calibration > 0)state_SMG ( 7 , duanma[param_calibration%10] );elsestate_SMG ( 7 , duanma[(-1*param_calibration)%10] );break; } } else if ( SMG_mode == 4 ){switch ( flash_count ){case 0:state_SMG ( 0 , duanma[15] );break;case 1:state_SMG ( 1 , duanma[2] );break;case 2:if ( param_V > 999 )state_SMG ( 4 , duanma[param_V/1000] );elsestate_SMG ( 4 , 0xff );break;case 3:if ( param_V > 99 )state_SMG ( 5 , duanma[param_V/100%10] );elsestate_SMG ( 5 , 0xff );break;case 4:if ( param_V > 9 )state_SMG ( 6 , duanma[param_V/10%10] );elsestate_SMG ( 6 , 0xff );break;case 5:state_SMG ( 7 , duanma[param_V%10] );break; }} else if ( SMG_mode == 5 ){switch ( flash_count ){case 0:state_SMG ( 0 , duanma[15] );break;case 1:state_SMG ( 1 , duanma[3] );break;case 2:state_SMG ( 6 , duanma_dot[param_dac/10] );break;case 3:state_SMG ( 7 , duanma[param_dac%10] );break;}}
} void reset_work ()
{SMG_mode = 1;param_distance = 40;param_temperature = 30;param_calibration = 0;param_V = 340;param_dac = 10;
}void init_timer0(void) //50微秒@12.000MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TMOD |= 0x02; //设置定时器模式TL0 = 0xCE; //设置定时初始值TH0 = 0xCE; //设置定时重载值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1;EA = 1;
}unsigned char count_50us = 0;
unsigned char count_10ms = 0;
bit flag_100ms = 0;
unsigned char count_save_10ms = 0;
unsigned char count_save_1s = 0;
unsigned char count_reset = 0;
void timer0_service () interrupt 1
{if ( ++count_50us == 200 ){count_50us = 0; if ( ++count_10ms == 200 )count_10ms = 0; if ( flag_save_distance == 1 ){if ( ++count_save_10ms == 100 ){count_save_10ms = 0;if ( ++count_save_1s == 6 )flag_save_distance = 0;}}else{count_save_10ms = 0;count_save_1s = 0;}if ( flag_reset == 1 ){if ( ++count_reset == 200 )reset_work();}elsecount_reset = 0;}if ( count_50us % 40 == 0 ) //刷新数码管和led{if ( SMG_mode == 1 ){if ( ++flash_count == 8 )flash_count= 0;}else if ( SMG_mode == 4 ){if ( ++flash_count > 5 )flash_count= 0;}else if ( SMG_mode == 2 || SMG_mode == 5 ){if ( ++flash_count > 3 )flash_count= 0;}else if ( SMG_mode == 3 ){if ( ++flash_count > 4 )flash_count= 0;}flash_SMG ();select_HC573 ( 4 , value_led );}if ( count_10ms % 50 == 0 ){flash_sonic = 1;}if ( count_10ms % 100 == 0 )//让温度和超声波不同时刷新,避免数据问题{flash_ds18b20 = 1; } if ( SMG_mode == 1 ){if ( dis_distance > 255 )value_led = 0x00;elsevalue_led = reverse_bit( ~(dis_distance/8) );}else if ( SMG_mode == 2 )value_led = 0x7f;else if ( SMG_mode > 2 ){if ( count_10ms % 10 == 0 )value_led = 0xfe;else value_led = 0xff;}}void value_work ()
{if ( flag_dac == 1 && save_distance != 0 ){ if ( save_distance > 90 )dac_value = 255;else if ( save_distance > 10 )dac_value = (3.2-0.05*param_dac)*save_distance;elsedac_value = param_dac*5.1;flag_dac = 0;}if ( dis_distance <= param_distance+5 && dis_distance >= param_distance-5 && dis_temperature <= param_temperature*10 )select_HC573 ( 5 , 0x10 );else select_HC573 ( 5 , 0x00 ); }void Delay2ms() //@12.000MHz
{unsigned char i, j;i = 24;j = 85;do{while (--j);} while (--i);
}void Delay30ms() //@12.000MHz
{unsigned char i, j, k;_nop_();_nop_();i = 2;j = 95;k = 43;do{do{while (--k);} while (--j);} while (--i);
}void scan_key ()
{if ( flag_save_distance == 1 )return;C1 = 0;C2 = R3 = R4 = 1;if ( R3 == 0 ){Delay2ms();if ( R3 == 0 ) //5{//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出if ( SMG_mode == 1 ){if ( flag_m_distance == 0 )flag_m_distance = 1;else if ( flag_m_distance == 1 )flag_m_distance = 0;}else if ( SMG_mode == 2 ){ if ( param_mode == 1 )param_mode = 2;else if ( param_mode == 2 )param_mode = 1; }else {switch ( SMG_mode ){case 3:SMG_mode = 4;break;case 4:SMG_mode = 5;break;case 5:SMG_mode = 3;break;}} while ( R3 == 0 );}}else if ( R4 == 0 ){Delay2ms();if ( R4 == 0 ) //4{ switch ( SMG_mode ){//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出case 1:SMG_mode = 2;param_mode = 1;break;case 2:SMG_mode = 3;break;case 3:case 4:case 5:SMG_mode = 1;break;} while ( R4 == 0 );}}C2 = 0;C1 = R3 = R4 = 1;if ( R3 == 0 || R4 == 0 ){Delay30ms();if ( R3 == 0 && R4 == 0 ){flag_reset = 1; while ( R3 == 0 && R4 == 0 ){flag_reset = 1; }flag_reset = 0; }else if ( R3 == 0 ) //9{//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出if ( SMG_mode == 2 && param_mode == 1 )param_distance -= 10;else if ( SMG_mode == 2 && param_mode == 2 )param_temperature -= 10;else if ( SMG_mode == 3 )param_calibration -= 5;else if ( SMG_mode == 4 ){param_V -= 10;value_sonic = (float)param_V/2/100;}else if ( SMG_mode == 5 )param_dac -=1;else if ( SMG_mode == 1 )flag_dac = 1; if ( param_distance < 10 )param_distance = 10;else if ( param_temperature > 100 ) //越位了会变成255param_temperature = 0;else if ( param_calibration < -90 )param_calibration = -90;else if ( param_V < 10 )param_V = 10;else if ( param_dac < 1 )param_dac = 1;value_sonic = (float)(param_V)*0.00005;while ( R3 == 0 );}else if ( R4 == 0 ) //8{//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出if ( SMG_mode == 2 && param_mode == 1 )param_distance += 10;else if ( SMG_mode == 2 && param_mode == 2 )param_temperature += 10;else if ( SMG_mode == 3 )param_calibration += 5;else if ( SMG_mode == 4 ){param_V += 10;value_sonic = (float)param_V*0.00005;}else if ( SMG_mode == 5 )param_dac +=1;else if ( SMG_mode == 1 )flag_save_distance = 1; if ( param_distance > 90 )param_distance = 90;else if ( param_temperature > 80 ) //越位了会变成255param_temperature = 80;else if ( param_calibration > 90 )param_calibration = 90;else if ( param_V > 9990 )param_V = 9990;else if ( param_dac > 20 )param_dac = 20; value_sonic = (float)(param_V)*0.00005;while ( R4 == 0 );}}
}void init_sys ()
{select_HC573 ( 4 , 0xff );select_HC573 ( 5 , 0x00 );value_sonic = (float)(param_V)*0.00005;
}void main ()
{init_sys ();init_timer0 ();init_pca ();while ( 1 ){scan_key ();value_work();recive_sonic ();recive_ds18b20 ();dac_work ( dac_value ); }
}