完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
精彩!!!
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-6-2 10:09 编辑
第三十四节:温度篇--利用DS18B20来采集温度 开场白: DS18B20是一款特别常用的温度传感器芯片,它只占用单片机一根IO口,使用起来也特别方便。需要特别注意的是,正因为它只用一根IO口跟单片机通讯,因此读取一次温度值的通讯时间比较长,而且时序要求严格,在通讯期间不允许单片机其它的中断干扰,因此系统一旦选用了这款传感器芯片,就千万不要选用动态扫描数码管的显示方式。否则在关闭中断读取温度的时候,数码管的显示会有“闪烁”的现象。 DS18B20的测温范围是-55度至125度。在-10度至85度的温度范围内误差是+-0.5度,能满足大部分常用的测温要求。 (1)功能需求: 利用8位数码管显示当前环境的温度,保留小数点后面四位。左边第1位数码管显示正负符号,第2,3,4位显示温度的整数部分,第5,67,8位显示小数点后面四位。 (2)硬件原理: (a) 专用集成芯片TM1639驱动8位数码管的电路请参考第二十五节。 (d) DS18B20的数据线一定要加一个15K左右的上拉电阻。 (3)源码适合的单片机: PIC18f4520,晶振为11.0592MHz。 (4)单片机的C语言源代码讲解如下: #include //DS18B20的IO宏定义 #define DQ RC7 #define DQ_HIGH() TRISC7=1 #define DQ_LOW() TRISC7=0;DQ=0 //tm1639的IO宏定义 #define tm1639_stb_dr LATA3 #define tm1639_clk_dr LATA4 #define tm1639_dio_dr LATA5 //位地址,共8位地址,每位地址里面的1个字节的数据代表8个LED灯的亮或灭 #define const_dig_addr0 0xc0 #define const_dig_addr1 0xc2 #define const_dig_addr2 0xc4 #define const_dig_addr3 0xc6 #define const_dig_addr4 0xc8 #define const_dig_addr5 0xca #define const_dig_addr6 0xcc #define const_dig_addr7 0xce //数码管或者LED灯的显示亮度级别 #define const_level_off 0x80 //级别最低,最暗 #define const_level_1 0x88 #define const_level_2 0x89 #define const_level_4 0x8a //本程序采取这个级别的亮度 #define const_level_10 0x8b #define const_level_11 0x8c #define const_level_12 0x8d #define const_level_13 0x8e #define const_level_14 0x8f //级别最高,最亮 #define const_auto_add_addr 0x40 //采用地址自动加一方式写显存 void delay(unsigned int x); //时序中用到的延时 void delayus(unsigned int x,unsigned char y); //时序中用到的延时 void write_byte(unsigned char date); //写入一个字节的时序 unsigned char read_byte(); //读取一个字节的时序 unsigned int get_temper(); //读取一次没有经过换算的温度数值 void write_byte_tm1639(unsigned char tm1639_byte); //写入一个字节数据进tm1639 void display_tm1639(unsigned char dig_addr,unsigned char dig_data,unsigned char dig_level); //一次显示8个LED灯或者一位数码管 //其中dig_addr是地址,dig_data是地址的数据,dig_level是亮度 void display_drive(); //数码管驱动程序,放在main函数的while(1)循环里 unsigned long temper=0; //经过换算后的温度数值,用来显示 unsigned int ds18b20_result=0; //没有经过换算后的ds18b20数值 unsigned char sign_flag=0; //符号标志。0表示是正,1表示负. unsigned int time_dly=0; //计数延时器。每次采集温度的时间间隔 unsigned char number_left1=0; //左边第1位数码管显示的内容 unsigned char number_left2=0; //左边第2位数码管显示的内容 unsigned char number_left3=0; //左边第3位数码管显示的内容 unsigned char number_left4=0; //左边第4位数码管显示的内容 unsigned char number_left5=0; //左边第5位数码管显示的内容 unsigned char number_left6=0; //左边第6位数码管显示的内容 unsigned char number_left7=0; //左边第7位数码管显示的内容 unsigned char number_left8=0; //左边第8位数码管显示的内容 unsigned char led_update=0; //更新显示变量,等于1时将执行一次更新显示数码管的程序 unsigned char number_temp[8]; //即将更新显示内容的中间变量 const unsigned char number_table[]= //数码管的字模转换表 { 0x3F, //0 0x06, //1 0x5B, //2 0x4F, //3 0x66, //4 0x6D, //5 0x7D, //6 0x07, //7 0x7F, //8 0x6F, //9 0x00, //10 空 什么不都显示 0x40, //11 显示负号"-" }; //主程序 main() { ADCON0=0x00; ADCON1=0x0f; //全部为数字信号 ADCON2=0xa1; //右对齐 RBPU=0; //上拉电阻 SSPEN=0; TRISC7=1; //DS18B20的IO口开机默认设置为输入 TRISA3=0; //TM1639的3根驱动IO之一 TRISA4=0; //TM1639的3根驱动IO之一 TRISA5=0; //TM1639的3根驱动IO之一 while(1) { CLRWDT(); //喂看门狗,大家不用过度关注此行 time_dly++; if(time_dly>=2000) //每次采集温度的时间间隔。由于本系统的实时性要求不高,每采集一次温度可以“休息一会再继续采集” { time_dly=0; //时间间隔计数器清零 GIE=0; //为了保证时序完整,禁止所有中断 ds18b20_result=get_temper(); //读取一次没有经过换算的温度数值 GIE=1; //打开总中断允许位 if((ds18b20_result&0xf800)==0xf800) //是负号 { sign_flag=1; } else //是正号 { sign_flag=0; } ds18b20_result=~ds18b20_result; //求补码 ds18b20_result=ds18b20_result+1; temper=0; //把int数据类型赋给long类型之前最好先清零 temper=ds18b20_result; temper=temper*625; //保留小数点后面4位。如果保留小数点后面3位则*62.5,2位则*6.25,1位则*0.625,整数则*0.0625 if(sign_flag==1) //是负号 { number_left1=11; //左边第1位数码管显示负号"-" } else //是正号 { number_left1=10; //左边第1位数码管显示"空",也就是什么都不显示 } if(temper>=1000000) { number_left2=temper/1000000; //左边第2位数码管显示百位数值 } else { number_left2=10; //如果数值不超过百位,则左边第2位数码管什么也不显示 } if(temper>=100000) { number_left3=temper%1000000/100000; //左边第3位数码管显示十位数值 } else { number_left3=10; //如果数值不超过十位,则左边第3位数码管什么也不显示 } number_left4=temper%100000/10000; //左边第4位数码管显示个位数值 number_left5=temper%10000/1000; //左边第5位数码管显示小数点后面第1位数值 number_left6=temper%1000/100; //左边第6位数码管显示小数点后面第2位数值 number_left7=temper%100/10; //左边第7位数码管显示小数点后面第3位数值 number_left8=temper%10; //左边第8位数码管显示小数点后面第4位数值 led_update=1; //更新显示 } display_drive(); //数码管驱动程序,放在main函数的while(1)循环里 } } void ds18b20_reset() //复位ds18b20的时序 { DQ_HIGH(); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); DQ_LOW(); delayus(210,30); DQ_HIGH(); delayus(12,4); delayus(150,10); } void write_byte(unsigned char date) //写入一个字节的时序 { unsigned char i,temp; DQ_HIGH(); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); for(i=8;i>0;i--) { temp=date&0x01;//01010101 DQ_LOW(); delayus(0,0); delayus(0,0); delayus(0,0); if(temp==1) { DQ_HIGH(); } delayus(6,2); DQ_HIGH(); date=date>>1; } } unsigned char read_byte() //读取一个字节的时序 { unsigned char i,date; static bit j; for(i=8;i>0;i--) { date=date>>1; DQ_HIGH(); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); DQ_LOW(); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); DQ_HIGH(); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); j=DQ; if(j==1) { date=date|0x80; } delayus(3,1); } return (date); } unsigned int get_temper() //读取一次没有经过换算的温度数值 { unsigned char temper_H; unsigned char temper_L; unsigned int ds18b20_data=0; ds18b20_reset(); //复位ds18b20的时序 write_byte(0xCC);//跳过ROM write_byte(0x44);//温度转换 asm("nop"); asm("nop"); asm("nop"); asm("nop"); ds18b20_reset(); //复位ds18b20的时序 write_byte(0xCC); write_byte(0xBE); temper_L=read_byte(); temper_H=read_byte(); ds18b20_data=temper_H; //把两个字节合并成一个int数据类型 ds18b20_data=ds18b20_data<<8; ds18b20_data=ds18b20_data|temper_L; return ds18b20_data; } void delayus(unsigned int x,unsigned char y) //延时时序 { unsigned int i; unsigned char j; for(i=x;i>0;i--); for(j=y;j>0;j--); } void delay(unsigned int x) //延时时序 { unsigned int a,b; for(a=x;a>0;a--) for(b=110;b>0;b--); } void display_drive() //数码管驱动程序,放在main函数的while(1)循环里 { if(led_update==1) //有数据更新 { led_update=0; //标志及时清零,避免一直扫描 number_temp[0]=number_table[number_left1]; //载入即将显示的内容 number_temp[1]=number_table[number_left2]; //载入即将显示的内容 number_temp[2]=number_table[number_left3]; //载入即将显示的内容 number_temp[3]=number_table[number_left4]; //载入即将显示的内容 number_temp[4]=number_table[number_left5]; //载入即将显示的内容 number_temp[5]=number_table[number_left6]; //载入即将显示的内容 number_temp[6]=number_table[number_left7]; //载入即将显示的内容 number_temp[7]=number_table[number_left8]; //载入即将显示的内容 display_tm1639(const_dig_addr0,number_temp[0],const_level_4); //显示左边第1位 display_tm1639(const_dig_addr1,number_temp[1],const_level_4); //显示左边第2位 display_tm1639(const_dig_addr2,number_temp[2],const_level_4); //显示左边第3位 display_tm1639(const_dig_addr3,number_temp[3],const_level_4); //显示左边第4位 display_tm1639(const_dig_addr4,number_temp[4],const_level_4); //显示左边第5位 display_tm1639(const_dig_addr5,number_temp[5],const_level_4); //显示左边第6位 display_tm1639(const_dig_addr6,number_temp[6],const_level_4); //显示左边第7位 display_tm1639(const_dig_addr7,number_temp[7],const_level_4); //显示左边第8位 } } //写入一个字节数据进tm1639 void write_byte_tm1639(unsigned char tm1639_byte) { unsigned char tm1639_i; tm1639_stb_dr=0; //stb为低电平,程序不依赖于之前端口的状态,避免出现“端口迷失” for(tm1639_i=0;tm1639_i<8;tm1639_i++) { tm1639_clk_dr=0; if((tm1639_byte & 0x01)!=0) tm1639_dio_dr=1; else tm1639_dio_dr=0; tm1639_clk_dr=1; tm1639_byte=tm1639_byte>>1; } } //一次显示8个LED灯或者一位数码管 void display_tm1639(unsigned char dig_addr,unsigned char dig_data,unsigned char dig_level) { tm1639_dio_dr=1; tm1639_clk_dr=1; tm1639_stb_dr=1; write_byte_tm1639(const_auto_add_addr); //设置成自动加一方式 tm1639_stb_dr=1; write_byte_tm1639(dig_addr); //设置显示的位地址 write_byte_tm1639(dig_data & 0x0f); //显示的低4位数据,共代表4个led灯 write_byte_tm1639(dig_data >> 4 & 0x0f); //显示的高4位数据,共代表4个led灯 tm1639_stb_dr=1; write_byte_tm1639(dig_level); //设置显示的亮度 tm1639_stb_dr=1; } (5)下集预告: 温湿度篇--利用DHT11来采集温湿度。 (未完待续,下节更精彩,不要走开哦!) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-6-2 13:07 编辑
第三十五节:温湿度篇--利用DHT11来采集温湿度 开场白: DHT11是一款集成了湿度和温度的传感器,它只占用单片机一根IO口,使用起来也特别方便。需要特别注意的是,正因为它只用一根IO口跟单片机通讯,因此读取一次温度值的通讯时间比较长,而且时序要求严格,在通讯期间不允许单片机其它的中断干扰,因此系统一旦选用了这款传感器芯片,就千万不要选用动态扫描数码管的显示方式。否则在关闭中断读取温度的时候,数码管的显示会有“闪烁”的现象。 DHT11的测湿度范围是20%至90%,误差是+-5%。 DHT11的测温度范围是0度至50度,误差是+-2度。 (1)功能需求: 利用8位数码管显示当前环境的温度和湿度,仅仅保留和显示整数部分,不保留也不显示小数部分。左边第1,2位数码管显示整数部分的湿度。第3,4,5,6位什么也不显示,代表温度和湿度的分割线。第7,8位显示整数部分的温度。 (2)硬件原理: (a) 专用集成芯片TM1639驱动8位数码管的电路请参考第二十五节。 (d) DHT11的数据线一定要加一个5K的上拉电阻。 (3)源码适合的单片机: PIC18f4520,晶振为11.0592MHz。 (4)单片机的C语言源代码讲解如下: #include //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的IO后缀都是_sr //DHT11的IO宏定义 #define DH_dr_sr RC4 //tm1639的IO宏定义 #define tm1639_stb_dr LATA3 #define tm1639_clk_dr LATA4 #define tm1639_dio_dr LATA5 //一些延时的阀值 #define delay_97us 7 #define delay_29us 2 #define cnt_DH 1000 #define cnt_hdt 100 // 读者移植时请根据实际情况修改cnt_hdt的大小 ,要产生18ms左右的延时 //位地址,共8位地址,每位地址里面的1个字节的数据代表8个LED灯的亮或灭 #define const_dig_addr0 0xc0 #define const_dig_addr1 0xc2 #define const_dig_addr2 0xc4 #define const_dig_addr3 0xc6 #define const_dig_addr4 0xc8 #define const_dig_addr5 0xca #define const_dig_addr6 0xcc #define const_dig_addr7 0xce //数码管或者LED灯的显示亮度级别 #define const_level_off 0x80 //级别最低,最暗 #define const_level_1 0x88 #define const_level_2 0x89 #define const_level_4 0x8a //本程序采取这个级别的亮度 #define const_level_10 0x8b #define const_level_11 0x8c #define const_level_12 0x8d #define const_level_13 0x8e #define const_level_14 0x8f //级别最高,最亮 #define const_auto_add_addr 0x40 //采用地址自动加一方式写显存 unsigned char readdht11_byte(); //读取DHT11的一个字节数据 void read_dht11(); //读温度湿度 void delay(unsigned long de); //时序的延时函数 void write_byte_tm1639(unsigned char tm1639_byte); //写入一个字节数据进tm1639 void display_tm1639(unsigned char dig_addr,unsigned char dig_data,unsigned char dig_level); //一次显示8个LED灯或者一位数码管 //其中dig_addr是地址,dig_data是地址的数据,dig_level是亮度 void display_drive(); //数码管驱动程序,放在main函数的while(1)循环里 unsigned char hum_int_temp=0; //湿度整数数据的中间变量 unsigned char hum_dec_temp=0; //湿度小数点后面的数据的中间变量 unsigned char temper_int_temp=0; //温度整数数据的中间变量 unsigned char temper_dec_temp=0; //温度小数点后面的数据的中间变量 unsigned char hum_int=0; //湿度整数数据 unsigned char hum_dec=0; //湿度小数点后面的数据 unsigned char temper_int=0; //温度整数数据 unsigned char temper_dec=0; //温度小数点后面的数据 unsigned char hdt_cnt=0; //超时计数器 unsigned int DH_cnt=0; //超时计数器 unsigned char hdt_step=1; //读取DHT11的采集时序步骤 unsigned char error_flag=1; //读写DHT11的出错标志 1表示对,0表示错 unsigned int time_dly=0; //计数延时器。每次采集温度的时间间隔 unsigned char number_left1=0; //左边第1位数码管显示的内容 unsigned char number_left2=0; //左边第2位数码管显示的内容 unsigned char number_left3=0; //左边第3位数码管显示的内容 unsigned char number_left4=0; //左边第4位数码管显示的内容 unsigned char number_left5=0; //左边第5位数码管显示的内容 unsigned char number_left6=0; //左边第6位数码管显示的内容 unsigned char number_left7=0; //左边第7位数码管显示的内容 unsigned char number_left8=0; //左边第8位数码管显示的内容 unsigned char led_update=0; //更新显示变量,等于1时将执行一次更新显示数码管的程序 unsigned char number_temp[8]; //即将更新显示内容的中间变量 const unsigned char number_table[]= //数码管的字模转换表 { 0x3F, //0 0x06, //1 0x5B, //2 0x4F, //3 0x66, //4 0x6D, //5 0x7D, //6 0x07, //7 0x7F, //8 0x6F, //9 0x00, //10 空 什么不都显示 }; //主程序 main() { ADCON0=0x00; ADCON1=0x0f; //全部为数字信号 ADCON2=0xa1; //右对齐 RBPU=0; //上拉电阻 SSPEN=0; TRISC4=1; //DHT11的IO口开机默认设置为输入 TRISA3=0; //TM1639的3根驱动IO之一 TRISA4=0; //TM1639的3根驱动IO之一 TRISA5=0; //TM1639的3根驱动IO之一 while(1) { CLRWDT(); //喂看门狗,大家不用过度关注此行 if(time_dly<2000) //每次采集温度的时间间隔。由于本系统的实时性要求不高,每采集一次温度可以“休息一会再继续采集” { time_dly++; //此计数延时的清零部分放在read_dht11()函数里 } else { read_dht11(); //读取湿度和温度值 } display_drive(); //数码管驱动程序,放在main函数的while(1)循环里 } } //读温度湿度 void read_dht11() { switch(hdt_step) { case 1: TRISC4=0; //设置数据线为输出 asm("nop"); DH_dr_sr=0; //数据线拉低>18ms ++hdt_cnt; if(hdt_cnt>cnt_hdt) //延时超过18ms,读者移植时请根据实际情况修改cnt_hdt的大小 { error_flag=1; //出错标志 1表示对,0表示错 hdt_cnt=0; hdt_step=2; } break; case 2: GIE=0; //为了保持时序的完整,禁止所有中断 DH_dr_sr=1; //拉高等待 delay(delay_29us); //延时29us TRISC4=1; //设置数据线为输入 asm("nop"); if(!DH_dr_sr) //如果数据线为低电平 { DH_cnt=0; //超时计数器清零 while(!DH_dr_sr) //等待数据线变成高电平 { CLRWDT(); DH_cnt++; if(DH_cnt>cnt_DH) //如果超时,就别一直傻傻地等下去 { DH_cnt=0; error_flag=0; //报错 break; } } DH_cnt=0; //超时计数器清零 while(DH_dr_sr) //等待数据线变成低电平 { CLRWDT(); DH_cnt++; if(DH_cnt>cnt_DH) //如果超时,就别一直傻傻地等下去 { DH_cnt=0; error_flag=0; //报错 break; } } hum_int_temp=readdht11_byte(); //读取湿度整数数据 hum_dec_temp=readdht11_byte(); //读取湿度小数数据 temper_int_temp=readdht11_byte(); //读取温度整数数据 temper_dec_temp=readdht11_byte(); //读取温度小数数据 if(hum_int_temp>100||temper_int_temp>100||error_flag==0) //出错了,则什么也干 { asm("nop"); //空指令 } else //采集的数据正确 ,则把数据传递给显示的变量 { hum_int=hum_int_temp; //湿度整数数据传递给相对应的显示变量 hum_dec=hum_dec_temp; //湿度小数数据传递给相对应的显示变量 temper_int=temper_int_temp; //温度整数数据传递给相对应的显示变量 temper_dec=temper_dec_temp; //温度小数数据传递给相对应的显示变量 if(hum_int>=10) { number_left1=hum_int/10; //左边第1位数码管显示湿度的十位 } else { number_left1=10; //如果数值不超过十位,则左边第1位数码管什么也不显示 } number_left2=hum_int%10; //左边第2位数码管显示湿度的个位 number_left3=10; //分割线,则左边第3位数码管什么也不显示 number_left4=10; //分割线,则左边第4位数码管什么也不显示 number_left5=10; //分割线,则左边第5位数码管什么也不显示 number_left6=10; //分割线,则左边第6位数码管什么也不显示 if(temper_int>=10) { number_left7=temper_int/10; //左边第7位数码管显示温度的十位 } else { number_left7=10; //如果数值不超过十位,则左边第7位数码管什么也不显示 } number_left8=temper_int%10; //左边第8位数码管显示温度的个位 led_update=1; //更新显示 } } GIE=1; //开总中断允许标志 time_dly=0; //每次采集温度的时间间隔计数器清零,重新开始计时 hdt_step=1; //采集时序步骤返回第一步,为下一次采集数据作准备 break; } } unsigned char readdht11_byte() //读取DHT11的一个字节数据 { unsigned char i,dht; for(i=8;i>0;i--) { dht=dht<<1; DH_cnt=0; CLRWDT(); while(!DH_dr_sr) //等待50ms { CLRWDT(); DH_cnt++; if(DH_cnt>cnt_DH) { DH_cnt=0; break; } } delay(delay_29us); //延时29us if(DH_dr_sr==1) { dht=dht|0x01; delay(delay_97us); //97us } else { delay(delay_29us); //延时29us } } return dht; } void delay(unsigned long de) //时序的延时函数 { unsigned long d; for(d=0;d CLRWDT(); } } void display_drive() //数码管驱动程序,放在main函数的while(1)循环里 { if(led_update==1) //有数据更新 { led_update=0; //标志及时清零,避免一直扫描 number_temp[0]=number_table[number_left1]; //载入即将显示的内容 number_temp[1]=number_table[number_left2]; //载入即将显示的内容 number_temp[2]=number_table[number_left3]; //载入即将显示的内容 number_temp[3]=number_table[number_left4]; //载入即将显示的内容 number_temp[4]=number_table[number_left5]; //载入即将显示的内容 number_temp[5]=number_table[number_left6]; //载入即将显示的内容 number_temp[6]=number_table[number_left7]; //载入即将显示的内容 number_temp[7]=number_table[number_left8]; //载入即将显示的内容 display_tm1639(const_dig_addr0,number_temp[0],const_level_4); //显示左边第1位 display_tm1639(const_dig_addr1,number_temp[1],const_level_4); //显示左边第2位 display_tm1639(const_dig_addr2,number_temp[2],const_level_4); //显示左边第3位 display_tm1639(const_dig_addr3,number_temp[3],const_level_4); //显示左边第4位 display_tm1639(const_dig_addr4,number_temp[4],const_level_4); //显示左边第5位 display_tm1639(const_dig_addr5,number_temp[5],const_level_4); //显示左边第6位 display_tm1639(const_dig_addr6,number_temp[6],const_level_4); //显示左边第7位 display_tm1639(const_dig_addr7,number_temp[7],const_level_4); //显示左边第8位 } } //写入一个字节数据进tm1639 void write_byte_tm1639(unsigned char tm1639_byte) { unsigned char tm1639_i; tm1639_stb_dr=0; //stb为低电平,程序不依赖于之前端口的状态,避免出现“端口迷失” for(tm1639_i=0;tm1639_i<8;tm1639_i++) { tm1639_clk_dr=0; if((tm1639_byte & 0x01)!=0) tm1639_dio_dr=1; else tm1639_dio_dr=0; tm1639_clk_dr=1; tm1639_byte=tm1639_byte>>1; } } //一次显示8个LED灯或者一位数码管 void display_tm1639(unsigned char dig_addr,unsigned char dig_data,unsigned char dig_level) { tm1639_dio_dr=1; tm1639_clk_dr=1; tm1639_stb_dr=1; write_byte_tm1639(const_auto_add_addr); //设置成自动加一方式 tm1639_stb_dr=1; write_byte_tm1639(dig_addr); //设置显示的位地址 write_byte_tm1639(dig_data & 0x0f); //显示的低4位数据,共代表4个led灯 write_byte_tm1639(dig_data >> 4 & 0x0f); //显示的高4位数据,共代表4个led灯 tm1639_stb_dr=1; write_byte_tm1639(dig_level); //设置显示的亮度 tm1639_stb_dr=1; } (5)下集预告: 从下一节开始,我准备专门花几章节的篇幅来讲常用的几种EPROM驱动方式。下一节的标题是:EPROM篇--利用单片机内部自带EPROM存储数据。 (未完待续,下节更精彩,不要走开哦!) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
很受用的,虽然没有全部学完,还是感谢版主的奉献精神。很期待外存EEPOM,FLASHROM的相关操作例程,特别是页写数据这一块,一直没有弄懂。期待中。。。
|
|
|
|
|
|
过两天就会来看看,想和鸿哥学习一下数据链表,消息队列这一块,比如串口接收数据,解包后,将任务加入消息队列,工作中经常听到这些,但是不明白是什么意思,什么场合会用,怎么使用等等。希望鸿哥有工程实践案例
|
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2086 浏览 1 评论
3630 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2336 浏览 2 评论
2763 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4029 浏览 5 评论
978浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6365浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 18:30 , Processed in 1.101365 second(s), Total 105, Slave 90 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号