菏泽炫佑网站建设,wordpress中没有链接,厦门seo结算,钢构网架公司51单片机系统浓缩图 1. HC138译码器 用3个输入引脚#xff0c;实现8个输出引脚#xff0c;而且这个八个输出引脚中只要一个低电平#xff0c;所以我们只需要记住真值表就行 #include reg52.h sbit HC138_A P2^5; sbit HC138_B P2^6; sbit HC… 51单片机系统浓缩图 1. HC138译码器
· 用3个输入引脚实现8个输出引脚而且这个八个输出引脚中只要一个低电平所以我们只需要记住真值表就行 #include reg52.h sbit HC138_A P2^5; sbit HC138_B P2^6; sbit HC138_C P2^7; void Init74HC138(unsigned char n){switch(n){case 4: //LEDHC138_A 0;HC138_B 0;HC138_C 1;break;case 5: //蜂鸣器与译码器HC138_A 1;HC138_B 0;HC138_C 1;break;case 6: //数码管位置HC138_A 0;HC138_B 1;HC138_C 1;break;case 7: //数码管内容HC138_A 1;HC138_B 1;HC138_C 1;break;case 8: //关闭所有设备HC138_A 0;HC138_B 0;HC138_C 0;break;}}2. HC573 573锁存器有20个引脚D1~D8是数据输入端Q1~Q8是数据输出端LE为锁存控制端。当锁存使能端LE为高时573的锁存对于数据是透明的也就是说输出同步。当锁存使能变低时符合建立时间和保持时间的数据会被锁存。使用其可以替换HC138两个功能相同
#include reg52.h
void SelectHC573(unsigned channel)
{switch(channel){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;case 0:P2 (P2 0x1f) | 0x00; break;}P2 (P2 0x1f) | 0x00;
}
两者的功能相同因此我们可以简便的来替代一下
void InitHC138 (unsigned char n)
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
} 3. 控制LED // 任务
/* 先让奇数的灯闪再让偶数的灯闪然后所有的灯闪3下最后依次点亮所有的灯然后再依次熄灭然后循环 */void LEDRunning(){char i 0;P0 0xaa;Delay(60000);P0 0x55;Delay(60000); for(i 0; i 3; i){P0 0x00; //全灭Delay(60000);P0 0xff; //全亮Delay(60000);}for(i 0; i 8; i){P0 1; //按顺序依次闪过Delay(60000);}for(i 0; i 8; i){P0 1;P0 | 1; //熄灭Delay(60000);}
}main(){Init74HC138(4); //打开LED的138 while(1){LEDRunning(); }} 4. 数码管 其中a、b、c、d、e、f、g、dp引脚分别对应8个段码该8个引脚通过74HC573锁存器与单片机的P0端口相连。另外有com1com4四个公共控制脚该应用为高电平则使能对应位的数码管。两个F3461BH一共有8个com控制引脚也是通过74HC573锁存器与单片机的P0端口相连的。因此在操控数码管显示的过程中也离不开74HC138译码器和74HC573锁存器。
// 段码
unsigned char code SMG_Duanma[18] {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};// 数码管延时函数
void Delay2(unsigned int t)
{while(t--){Display_SMG();}
}//数码管显示函数
void DisplaySMG_bit(unsigned char value,unsigned char pos) //value为内容pos为所填位置、
{Init74HC138(6);P0 (0x01 pos);Init74HC138(7);P0 value;} 任务 在 8 位数码管中左边 4 位数码管显示 年份“2018”接着 2 位是分隔符“--”靠右的2 位数码管显示月份。从 1 月份开始每隔一段时间加 1 个月到 12 月之后又从 1 月开始递增 如此循环往复。 #include reg52.hunsigned char code SMG_duanma[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char yue1;
void Delay(unsigned int t)
{while(t--);
}void InitHC138 (unsigned char n) //ͨµÀÑ¡Ôñ
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
}void ShowSMG_Bit(unsigned char dat,unsigned int pos)
{InitHC138(6); //ÊýÂë¹ÜµÄλÖÃP00X01pos;InitHC138(7); //ÊýÂë¹ÜµÄÄÚÈÝP0dat;
}void Display_SMG()
{ShowSMG_Bit(SMG_duanma[2],0);Delay(500);ShowSMG_Bit(SMG_duanma[0],1);Delay(500);ShowSMG_Bit(SMG_duanma[1],2);Delay(500);ShowSMG_Bit(SMG_duanma[8],3);Delay(500);ShowSMG_Bit(SMG_duanma[16],4);Delay(500);ShowSMG_Bit(SMG_duanma[16],5);Delay(500);ShowSMG_Bit(SMG_duanma[yue/10],6);Delay(500);ShowSMG_Bit(SMG_duanma[yue%10],7);Delay(500);}void Delay2(unsigned int t)
{while(t--){Display_SMG();}
}void InitSystem()
{InitHC138(5); //¹Ø±Õ¼ÌµçÆ÷P00x00;InitHC138(4); //´ò¿ªµÆP00xff;P20x00; //¹Ø±ÕHC138
}void main()
{InitSystem();while(1){Display_SMG();yue;if(yue12)yue1;Delay2(100);}
} 5. 独立按键 一般情况下独立按键有两个引脚其中一个通过上拉电阻接到单片机的I/O端口另外一端接地。也就是说平时按键没有动作的时候输出的是高电平如果有按下动作发生则输出的是低电平。那么我们在程序设计的时候只要扫描跟按键引脚相连的I/O端口如果发现有低电平产生则判定该按键处于按下状态。有些时候电路或者外围有电磁干扰也会使单片机的I/O端口产生低电平这种干扰信号会让单片机误认为是按键动作。所以在扫描按键的时候应该做去抖动处理把干扰信号过滤掉从而获得准确的按键状态信号。 // 按键扫描
void ShowKeyNum(unsigned char value){Init74HC138(6); //数码管位置P0 0x01;Init74HC138(7); //数码管内容P0 value;}void ScanKeys(){if(S7 0){Delay(200);if(S7 0){while(S7 0);ShowKeyNum(SMG_NoDot[1]);}}if(S6 0){Delay(200);if(S6 0){while(S6 0);ShowKeyNum(SMG_NoDot[2]);}}if(S5 0){Delay(200);if(S5 0){while(S5 0);ShowKeyNum(SMG_NoDot[3]);}}if(S4 0){Delay(200);if(S4 0){while(S4 0);ShowKeyNum(SMG_NoDot[4]);}}} 6 .矩阵键盘的使用 与独立按键不同的是按键的两个引脚都分别连接的单片机的I/O端口一个作为行信号另外一个作为列信号。 对与矩阵键盘我们只能逐行扫描然后读取列的状态信号。如果R3行输出低电平那么黄色按键如果有按下动作的话那读取C2列信号也应该为低电平而该行上其他没有按下动作的按键的列信号则为高电平。因此我们可以得到矩阵键盘的基本扫描步骤 1 R1输出低电平R2、R3、R4输出高电平逐个读取判断列信号如果都为高电平则R1行上没有按键按下。 2 R2输出低电平R1、R3、R4输出高电平逐个读取判断列信号。 3 R3输出低电平R1、R2、R4输出高电平发现C2列信号为低电平那么可以判断得R3行的C2列的按键有按下动作。 4 R4输出低电平R1、R3、R4输出高电平逐个读取判断列信号。 任务 1、将 CT107D 上 J5 处跳帽接到 12 引脚使 S4 到 S19 成为 4X4 的矩阵键盘。 2、系统上电后关闭蜂鸣器关闭继电器关闭 8 个 LED 灯。 3、循环扫描矩阵键盘状态发现有按键按下等待其松开后在数码管的最左边 1 位 显示相应的数字。从左至右从上到下依次显示“0”到“F”。即按下 S7显示“0” 按下 S11 显示“1”按下 S15 显示“2”按下 S6 显示“4”...依次类推。 #include reg52.h
unsigned char code SMG_duanma[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
sfr P40xc0;
sbit R1P3^0;
sbit R2P3^1;
sbit R3P3^2;
sbit R4P3^3;sbit C4P3^4;
sbit C3P3^5;
sbit C2P4^2;
sbit C1P4^4;void InitHC138 (unsigned char n) //ͨµÀÑ¡Ôñ
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
}void DisplayKeyNum(unsigned char value)
{InitHC138(6);P00x01;InitHC138(7);P0value;
}unsigned char keynum;
void ScanKey()
{//µÚÒ»ÐÐR10;R2R3R41;C1C2C3C41;if(C10){while(C10);keynum0;DisplayKeyNum(SMG_duanma[keynum]);}else if(C20){while(C20);keynum1;DisplayKeyNum(SMG_duanma[keynum]);}else if(C30){while(C30);keynum2;DisplayKeyNum(SMG_duanma[keynum]);}else if(C40){while(C40);keynum3;DisplayKeyNum(SMG_duanma[keynum]);}//µÚ¶þÐÐR20;R1R3R41;C1C2C3C41;if(C10){while(C10);keynum4;DisplayKeyNum(SMG_duanma[keynum]);}else if(C20){while(C20);keynum5;DisplayKeyNum(SMG_duanma[keynum]);}else if(C30){while(C30);keynum6;DisplayKeyNum(SMG_duanma[keynum]);}else if(C40){while(C40);keynum7;DisplayKeyNum(SMG_duanma[keynum]);}//µÚÈýÐÐR30;R2R1R41;C1C2C3C41;if(C10){while(C10);keynum8;DisplayKeyNum(SMG_duanma[keynum]);}else if(C20){while(C20);keynum9;DisplayKeyNum(SMG_duanma[keynum]);}else if(C30){while(C30);keynum10;DisplayKeyNum(SMG_duanma[keynum]);}else if(C40){while(C40);keynum11;DisplayKeyNum(SMG_duanma[keynum]);}//µÚËÄÐÐR40;R1R2R31;C1C2C3C41;if(C10){while(C10);keynum12;DisplayKeyNum(SMG_duanma[keynum]);}else if(C20){while(C20);keynum13;DisplayKeyNum(SMG_duanma[keynum]);}else if(C30){while(C30);keynum14;DisplayKeyNum(SMG_duanma[keynum]);}else if(C40){while(C40);keynum15;DisplayKeyNum(SMG_duanma[keynum]);}}void InitSystem()
{InitHC138(5); P00x00;InitHC138(4);P00xff;P20x00;
}void main()
{InitSystem();while(1){ScanKey();}} 7. 中断相关寄存器 一般来说51单片机有5个中断源忽略定时/计数器2分2个优先级这个5个中断源按照自然优先级从高到低依次为 外部中断0INT0 定时/计数器0TF0 外部中断1INT1 定时/计数器1TF1 串口中断RI/TI 中断相关的寄存器有4个每个寄存器都是可以位寻址的这该编程带来了方便。 其中2个为控制寄存器IE寄存器与IP寄存器 另外2个为中断请求标志TCON寄存器与SCON寄存器 一般情况下中断的处理函数有两个其一为中断初始化函数其二为中断服务函数。初始化函数就是一个普通的函数而中断服务函数却有特殊的格式要求 1 中断函数没有返回值也不能带参数。 2 函数名后面要跟一个关键字interrupt说明这是一个中断服务函数。 3 在关键字interrupt后面要跟上中断号说明这个中断服务函数是为那个中断服务的。 8.定时器 51单片机有两个定时/计数器T0和T1为16位加法计数器由低8位TLx和高8位THx两个寄存器组成最大计数值为65535个计数脉冲。 该加1计数器的计数脉冲来源有2个 1 系统时钟振荡器输出的12分频。 2 T0或T1引脚输入的外部脉冲信号。 每接收到一个计数脉冲计数器就会加1当计数值累计至全为1时8位25513位819116位65535再输入一个计数脉冲计数器便会溢出回零并且计数器的溢出是TCON寄存器的TF0或TF1位置1同时向内核提出中断请求。如果定时/计数器工作于定时模式则表示间隔定时时间到如果工作与计数模式则表示计数值已满。 假设单片机的外部晶振为12MHz那么经过12分频后输入计数器的计数脉冲为1MHz即每个脉冲的周期为1us。因此定时器T0的16位工作模式最大的定时时间为65535us65.5ms。如果要定时10ms的话计数器就不能够从0开始计数了必须给它一个计数初值。怎么计算这个初值呢 要定时10ms则相当于计数10000个脉冲后计数器的值就到达65535了那么开始计数的这个地方就是计数初值。 65535 - 10000 55535 0xd8ef 把这个计算得到的初值写入TH0和TL0寄存器即可 TH0 0xd8或者 TH0 (65535 - 10000) / 256; TL0 0xef; 或者 TL0 (65535 - 10000) % 256; 定时/计数器相关的寄存器除了计数初值寄存器THx和TLx之外就是TMOD寄存器和TCON寄存器务必掌握。 1 TMOD模式控制寄存器不能进行位寻址只能字节操作。 2 TCON中断标志寄存器 定时/计数器的程序设计中通常有两个函数初始化函数和中断服务函数。 在初始化函数中一般需要进行以下几个配置 1 配置工作模式即对TMOD寄存器编程。 2 计算技术初值即对THx和TLx寄存器进行赋值。 3 使能定时/计数器中断即ET0或ET1置1。 4 打开总中断即EA 1。 5 启动定时器即TR0或TR1置1。 在中断服务函数中一般需要进行以下的编程 1 如果不是自动重装模式需要对THx和TLx重新赋值。 2 进行间隔定时到达的逻辑处理越少越好。 1、系统上电后关闭蜂鸣器关闭继电器关闭 8 个 LED 灯。 2、利用定时/计数器 T0 的模式 1 实现 50ms 的间隔定时。 3、在 50ms 间隔定时的基础上每隔 1 秒 L1 指示灯闪烁一次即 L1 指示灯循环点亮 0.5 秒熄灭 0.5 秒。 4、每隔 10 秒 L8 指示灯闪烁 1 次即 L1 指示灯循环点亮 5 秒熄灭 5 秒 #include reg52.h sbit HC138_A P2^5;
sbit HC138_B P2^6;
sbit HC138_C P2^7; sbit LED1 P0^0;
sbit LED2 P0^1; void Init74HC138(unsigned char n)
{switch(n){case 4:HC138_A 0;HC138_B 0;HC138_C 1;break;case 5:HC138_A 1;HC138_B 0;HC138_C 1;break;case 6:HC138_A 0;HC138_B 1;HC138_C 1;break;case 7:HC138_A 1;HC138_B 1;HC138_C 1;break;case 8:HC138_A 0;HC138_B 0;HC138_C 0;break;}
}
/*初始化定时器0*/
void Init_Timer0()
{TMOD 0x01; //16位定时模式TH0 (65536 - 50000) / 256; //定时50msTL0 (65536 - 50000) % 256;ET0 1; //使能定时器T0中断EA 1; //使能总中断 TR0 1; //启动定时器T0
}
/*定时器0中断服务函数*/
unsigned char count 0;
void SeviceTimer0() interrupt 1
{TH0 (65536 - 50000) / 256;TL0 (65536 - 50000) % 256;count;if(count 10) //0.5秒定时到{LED1 ~LED1;}if(count 20) //1秒定时到{LED2 ~LED2;count 0;}
}
/*主函数*/
main()
{Init74HC138(4);Init_Timer0();while(1);
} 9. PWM控制 1、系统上电后关闭蜂鸣器关闭继电器关闭 8 个 LED 灯。 2、PWM 脉宽信号的频率为 100Hz。 3、L1 指示灯有 4 种亮度分别是完全熄灭、10%的亮度、50%的亮度和 90%的亮度。 4、按下 S7 按键循环切换 L1 指示灯的四种亮度模式 #include reg52.h
#include HC573.h
#includd SMG.hsbit L1 P0^0;
sbit S7 P3^0;/*¶¨Ê±Æ÷Ïà¹Ø*/
unsigned char count 0;void InitTimer0()
{TMOD 0x01; //ʹÓö¨Ê±Æ÷1µÄ16λģʽTH0 (65535 - 100)/256 // ¼ÆÊý³õÖµTL0 (65535 - 100)%256ET0 1;EA 1;TR0 1;
}void ServiceTimer0() interrupt 1
{TH0 (65535 - 100)/256 // ¼ÆÊý³õÖµTL0 (65535 - 100)%256count;if(count pwm_duty){L1 1;}if(count 100){L1 0;count 0;}
}// °´¼ü
unsigned char stat 0;
void Scankeys()
{if(S7 0){Delay(200)if(S7 0){switch(stat){case 0:L1 0; //¿ªµÆpwm_duty 10;stat 1;break;case 1:pwm_duty 50;stat 2;break;case 1:pwm_duty 90;stat 3;break;case 3:L1 0;stat 0;break; }}}
}10. 串行接口 在串口通信的程序设计中主要有串口初始化和数据收发两个部分。 在初始化函数中基本步骤如下 1 设置定时器1的工作模式也就是对TMOD寄存器赋值。 2 计算波特率参数并赋值给TH1和TL1寄存器。 3 打开定时器1。 如果使用的是STC 12系统单片机则要设置AUXR寄存器。 4 设置SCON寄存器。 5 使能串口中断ES。 6 使能总中断EA。 1、初始化串口为模式 1即 8 位 UART 模式波特率 9600允许接收。 2、数据发送采用查询方式数据接收采用中断方式。 3、系统上电初始化之后单片机向上位机发送两个字节 0x5a 和 0xa5串口助手以十六进制 HEX 发送和显示。 4、串口每成功接收到一个字节后在该字节基础上加 1 然后通过串口发送回上位机。 5、注意 89C52 单片机和 IAP15F2K61S2 单片机串口应用的 差别使用 9600 波特率时晶振时钟选择 11.0592MHz。 #include reg52.h sfr AUXR0x8e;unsigned char tmpRecv;
void Init_Uart()
{TMOD0x20; TH10xfd;TL10xfd; AUXR0x00;TR11; SCON 0x50; ES1; EA1;
}void SendByte(unsigned char dat)
{SBUF dat; while(TI 0);TI 0;
}main()
{Init_Uart();SendByte(0x5a);SendByte(0xa5);while(1);
} 一般情况下上位机的命令可能不是一个字节而是多个字节组成的命令帧有的长度固定有的长度变化而且要求返回的数据可能也不是一个字节可能是一个数组也有可能是一个字符串等。在蓝桥杯的比赛中也不可能让你只是收发一个字节而已因此在串口这一个单元中必须多加一个强化环境掌握多字节的数据帧收发应用。 1、初始化串口为模式 1即 8 位 UART 模式波特率 9600允许接收。
2、数据发送采用查询方式数据接收采用中断方式。
3、系统上电后关闭蜂鸣器关闭继电器关闭 8 个 LED 灯通过串口向上位机发送
字符串“Welcome to XMF system”回车换行。
4、上位机通过串口发送单字节命令控制单片机的 8 个 LED 灯开关单片机响应正确
的控制命令后完成相应的灯光操作。
5、上位机通过串口发送单字节命令读取单片机运行信息单片机响应正确的读取命
令后向上位机返回指定的信息。 串口初始化函数Init_Uart()和单字节发送函数SendByte()就不需要修改拷过来就能用 1 字符发送 2字符接收 3命令解析与执行 11.DS1802温度传感器 在蓝桥杯“单片机设计与开发”赛项中会提供一个关于DS18B20的库文件里面有传感器复位、写字节和读字节三个函数。所以你不一定要把单总线的时序搞清楚但你一定要把DS18B20的基本操作流程弄明白。 通过单线总线端口访问DS18B20的协议如下 步骤1 复位初始化 步骤2 ROM操作指令 步骤3 DS18B20功能指令 三个重要的指令 1 CCH跳过ROM指令忽略64位ROM地址直接向DS18B20发起各种温度转换指令。 2 44H温度转换指令启动DS18B20进行温度转换转换时间最长为500ms典型值为200ms结果保存在高速RAM中。 3 BEH读暂存器指令读取高速暂存存储器9个字节的内容。 读取一次温度传感器数值的操作 1 主机对DS18B20进行复位初始化。 2 主机向DS18B20写0xCC命令跳过ROM。 3 主机向DS18B20写0x44命令开始进行温度转换。 4 等待温度转换完成。 5 主机对DS18B20进行复位初始化。 6 主机向DS18B20写0xCC命令跳过ROM。 7 主机向DS18B20写0xBE命令依次读取DS18B20发出的从第0一第8共九个字节的数据。如果只想读取温度数据那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可或者通过DS18B20复位停止数据的输出。 如果你利用大赛提供的DS18B20的库文件也就是onewire.c和onewire.h进行程序设计的时候没能正确的读出温度传感器的数值对库文件中代码的时序进行适当的调整即可。、 onewire.h
#include reg52.hsbit DQ P1^4; void Delay_OneWire(unsigned int t)
{while(t--);
}void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i0;i8;i){DQ 0;DQ dat0x01;Delay_OneWire(50);DQ 1;dat 1;}Delay_OneWire(50);
}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(50);}return dat;
}bit init_ds18b20(void)
{bit initflag 0;DQ 1;Delay_OneWire(120);DQ 0;Delay_OneWire(800);DQ 1;Delay_OneWire(100); initflag DQ; Delay_OneWire(50);return initflag;
}温度传感器任务 1、将 DS18B20 的底层驱动代码文件正确移植到工程中。 2、循环采样启动 DS18B20 进行温度转换。 3、将 DS18B20 的温度转换结果读出进行换算保留 1 位 小数并显示在数码管靠右端显示格式如图。 4、注意在进行 DS18B20 底层驱动代码文件移植时需确 认单总线的时序参数是否匹配 12. DS1302时钟系统 任务如下 1、将 DS1302 的底层驱动代码文件正确移植到工程中。 2、初始化 DS1302 的默认启动参数为 20 年 4 月 19 日 23 时 58 分 24 秒周六。 3、系统上电后DS1302 实时时钟从默认参数启动运行并 将当前的时、分、秒显示在数码管上时分秒之间用“-”分隔。 显示格式如图 /*³ÌÐò˵Ã÷: DS1302Çý¶¯³ÌÐòÈí¼þ»·¾³: Keil uVision 4.10 Ó²¼þ»·¾³: CT107µ¥Æ¬»ú×ÛºÏʵѵƽ̨ 8051£¬12MHzÈÕ ÆÚ: 2011-8-9
*/#include reg52.h
#include intrins.hsbit SCKP1^7;
sbit SDAP2^3;
sbit RST P1^3; // DS1302¸´Î» void Write_Ds1302(unsigned char temp)
{unsigned char i;for (i0;i8;i) { SCK0;SDAtemp0x01;temp1; SCK1;}
} void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{RST0; _nop_();SCK0; _nop_();RST1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST0;
}unsigned char Read_Ds1302_Byte ( unsigned char address )
{unsigned char i,temp0x00;RST0; _nop_();SCK0; _nop_();RST1; _nop_();Write_Ds1302(address);for (i0;i8;i) { SCK0;temp1; if(SDA)temp|0x80; SCK1;} RST0; _nop_();SCK0; _nop_();SCK1; _nop_();SDA0; _nop_();SDA1; _nop_();return (temp);
}DS1302时钟模块 #include reg52.h
#include ds1302.h
unsigned char Write_DS1302[7]{0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Read_DS1302[7]{0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char Timer[7]{0x50,0x59,0x12,0x18,0x04,0x06,0x22};
unsigned char code SMG_DM[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void SelectHC138(unsigned char n)
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
}
void DS1302_Config()
{unsigned char i;Write_Ds1302_Byte(0x8e,0x00);for(i0;i7;i){Write_Ds1302_Byte(Write_DS1302[i], Timer[i]);}Write_Ds1302_Byte(0x8e,0x80);}
void Read_DS1302_Timer()
{unsigned char i;for(i0;i7;i){Timer[i]Read_Ds1302_Byte(Read_DS1302[i]);}if(Timer[2]0x12){Timer[2]-0x12;}
}
void Delay_SMG(unsigned int t)
{while(t--);
}
void SMG_Bit(unsigned char dat,unsigned char pos)
{SelectHC138(6);P00x01pos;SelectHC138(7);P0SMG_DM[dat];
}
void Display_SMG()
{SMG_Bit(Timer[2]/16,0);Delay_SMG(100);SMG_Bit(Timer[2]%16,1);Delay_SMG(100);SMG_Bit(16,2);Delay_SMG(100);SMG_Bit(Timer[1]/16,3);Delay_SMG(100);SMG_Bit(Timer[1]%16,4);Delay_SMG(100);SMG_Bit(16,5);Delay_SMG(100);SMG_Bit(Timer[0]/16,6);Delay_SMG(100);SMG_Bit(Timer[0]%16,7);Delay_SMG(100);}void InitSystem()
{SelectHC138(5);P00x00;SelectHC138(4);P00xff;
}
void main()
{InitSystem();DS1302_Config();while(1){Read_DS1302_Timer();Display_SMG();}} 13. 频率测试 #include reg52.h
unsigned char code SMG_DM[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned int count_f0;
unsigned int dat0;
unsigned char count_s0;
void SelectHC138(unsigned char n)
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
}
//ÊýÂë¹ÜÏÔʾ
void Delay_SMG(unsigned int t)
{while(t--);
}
void SMG_Bit(unsigned char dat,unsigned char pos)
{SelectHC138(6);P00x01pos;SelectHC138(7);P0dat;
}
void Display_SMG()
{SMG_Bit(SMG_DM[15],0);Delay_SMG(500);SMG_Bit(0xff,1);Delay_SMG(500);SMG_Bit(0xff,2);Delay_SMG(500);if(dat9999){SMG_Bit(SMG_DM[dat/10000],3);Delay_SMG(500);}if(dat999){SMG_Bit(SMG_DM[(dat/1000)%10],4);Delay_SMG(500);}if(dat99){SMG_Bit(SMG_DM[(dat/100)%10],5);Delay_SMG(500);}if(dat9){SMG_Bit(SMG_DM[(dat/10)%10],6);Delay_SMG(500);}SMG_Bit(SMG_DM[dat%10],7);Delay_SMG(500);
}
//¶¨Ê±Æ÷
void Init_Timer()
{TMOD0x16;//¶¨Ê±Æ÷0ÓÃ×÷¼ÆÊý 0110TH00xff;TL00xff;//¶¨Ê±Æ÷1ÓÃ×÷¶¨Ê± 0001TH1(65535-50000)/256;TL1(65535-50000)%256;ET01;ET11;EA1;TR01;TR11;}void Service_T0() interrupt 1
{count_f;
}
void Service_T1() interrupt 3
{TH1(65535-50000)/256;TL1(65535-50000)%256;count_s;if(count_s20){datcount_f;count_f0;count_s0;}
}
void InitSystem()
{SelectHC138(5);P00x00;SelectHC138(4);P00xff;
}void main()
{InitSystem();Init_Timer();while(1){Display_SMG();}
} 14. 2402C存储器使用 在使用前我们得先明白其是通过IIC总线通信的 没有硬件IIC外设的微处理器中需要根据总线时序设计IIC接口的驱动程序。包括起始信号、停止信号、产生应答、等待应答、发送数据和接收数据6个函数。下面以51单片机为例阐述IIC总线驱动程序的设计。 //IIC#include reg52.h
#include intrins.h#define DELAY_TIME 5#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1sbit 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(i0; i8; 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(i0; i8; i){ SCL 1;IIC_Delay(DELAY_TIME);da 1;if(SDA) da | 1;SCL 0;IIC_Delay(DELAY_TIME);}return da;
}一般情况下所提供的IIC总线底层驱动代码有“ **.c ”和“ **.h ”两个文件你需要懂得它们至少需要了解“ **.h” 头文件才能正确应用。虽然不再需要编写IIC总线的底层驱动代码但是对于具体设备的操作还需要结合数据手册来进一步实现而IIC是需要用在我们的这个24C02存储器当中的 24C02存储器 #include reg52.h
#include iic.h
unsigned char code SMG_DM[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char dat1 0, dat2 0, dat3 0;//字节写操作
void SelectHC138(unsigned char n)
{switch(n){case 4:P2(P20x1f)|0x80;break;case 5:P2(P20x1f)|0xa0;break;case 6:P2(P20x1f)|0xc0;break;case 7:P2(P20x1f)|0xe0;break;}
}
void Delay(unsigned int t)
{while(t--);
}
void Write_24C02(unsigned char addr, unsigned char dat)
{IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(addr); IIC_WaitAck(); IIC_SendByte(dat); IIC_WaitAck(); IIC_Stop();
}//字节读操作
unsigned char Read_24C02(unsigned char addr)
{unsigned char tmp;//½øÐÐÒ»¸öαд²Ù×÷IIC_Start(); //IIC×ÜÏ߯ðʼÐźŠIIC_SendByte(0xa0); //24C02дÉ豸µØÖ·IIC_WaitAck(); //µÈ´ý´Ó»úÓ¦´ðIIC_SendByte(addr); //ÄÚ´æ×Ô¼ºµØÖ·IIC_WaitAck(); //µÈ´ý´Ó»úÓ¦´ð//½øÐÐ×Ö½Ú¶Á²Ù×÷IIC_Start(); //IIC×ÜÏ߯ðʼÐźŠIIC_SendByte(0xa1); //24C02¶ÁÉ豸µØÖ·IIC_WaitAck(); //µÈ´ý´Ó»úÓ¦´ðtmp IIC_RecByte(); //¶ÁȡĿ±êÊý¾ÝIIC_SendAck(1); //²úÉú·ÇÓ¦´ðÐźÅIIC_Stop(); //IIC×ÜÏßÍ£Ö¹ÐźŠreturn tmp;
}//数据读写函数
void Read_Write()
{dat1 Read_24C02(0x01);dat2 Read_24C02(0x03);dat3 Read_24C02(0x05);dat1 dat1 1;dat2 dat2 2;dat3 dat3 3;if(dat1 10)dat1 0;if(dat2 20)dat2 0;if(dat3 30)dat3 0;Write_24C02(0x01, dat1);Delay(1100);Write_24C02(0x03, dat2);Delay(1100);Write_24C02(0x05, dat3);Delay(1100);
}
//数码管显示函数
void SMG_Bit(unsigned char dat,unsigned char pos)
{SelectHC138(6);P00x01pos;SelectHC138(7);P0SMG_DM[dat];
}//显示函数
void Display_24c02()
{SMG_Bit(dat1/10,0);Delay(500);SMG_Bit(dat1%10,1);Delay(500);SMG_Bit(16,2);Delay(500);SMG_Bit(dat2/10,3);Delay(500);SMG_Bit(dat2%10,4);Delay(500);SMG_Bit(16,5);Delay(500);SMG_Bit(dat3/10,6);Delay(500);SMG_Bit(dat3%10,7);Delay(500);
}// 初始化函数
void InitSystem()
{SelectHC138(5);P00x00;SelectHC138(4);P00xff;
}void main()
{InitSystem();Read_Write();while(1){Display_24c02();}} 15.PWM呼吸灯 任务如下 1、将 J5 的 23 脚短接把 S4 和 S7 设置为独立按键。 2、系统上电后关闭蜂鸣器和继电器L4 和 L5 指示灯点亮其余的指示灯熄灭。 3、按下 S4 按键松开后L1 到 L8 八个指示灯进行每隔 1 秒的呼吸流水点亮。控制流 程为L1 缓慢点亮-L1 缓慢熄灭-L2 缓慢点亮-L2 缓慢熄灭...L8 缓慢点亮-L8 缓慢熄 灭-L1 缓慢点亮-L1 缓慢熄灭...如此循环往复。 4、再次按下 S4 按键松开后L1 到 L8 八个指示灯从当前状态开始逆向呼吸流水点亮。 如果当前的水方向为L1 缓慢点亮-L1 缓慢熄灭-L2 缓慢点亮-L2 缓慢熄灭...那么按 下 S4 按键松开后为 L2 缓慢点亮-L2 缓慢熄灭-L1 缓慢点亮-L1 缓慢熄灭-L8 缓慢点亮 -L8 缓慢熄灭-L7 缓慢点亮-L7 缓慢熄灭...如此循环往复。 5、对于每个 LED 指示灯缓慢点亮的时长为 0.5 秒缓慢熄灭的时长为 0.5 秒。 6、按下 S4 按键时当前的指示灯暂停流水变化并保持现有的亮度直到按键松开后 亮度才开始恢复变化。待当前的亮度变化完成后才开始改变呼吸流水控制的方向。 7、按下 S7 按键时在数码管上显示当前 LED 指示灯的 位置和 PWM 脉宽调制信号的占空比。按键松开后数码管熄 灭。显示格式如图在数码管左边的第 1 位数码管显示 LED 指示灯的位置在数码管右边的 2 位数码管显示 PWM 信号占 空比。例如当前点亮 L6 指示灯PWM 信号的占空比为 30% 那么数码管最左边的 1 位显示“6”在最右边的 2 位显示 “30”其余没有使用的数码管熄灭。 8、按下 S7 按键时当前的指示灯暂停流水变化并保持现有的亮度直到按键松开后 亮度才开始恢复变化 #include regx52.h
#include absacc.hsbit S7 P3^0;
sbit S4 P3^3;unsigned char pwm 0;
unsigned char pwm_duty 0;
unsigned char times 0;
unsigned char led_go 0;
unsigned char stat_go 0;
unsigned char stat 0;
unsigned char key_puse 0; unsigned char code SMG_duanma[18]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};void DelaySMG(unsigned int t)
{while(t--);
}void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{XBYTE[0xE000] 0xff;XBYTE[0xC000] 0x01 pos;XBYTE[0xE000] value;
}void Display_Info(unsigned char pos, unsigned char duty)
{DisplaySMG_Bit(0, SMG_duanma[pos]);DelaySMG(500);DelaySMG(500);DisplaySMG_Bit(6, SMG_duanma[duty / 10]);DelaySMG(500);DisplaySMG_Bit(7, SMG_duanma[duty % 10]); DelaySMG(500);DisplaySMG_Bit(0, 0xff);DisplaySMG_Bit(6, 0xff);DisplaySMG_Bit(7, 0xff);
}void Init_Timer0()
{TMOD 0x01;TH0 (65535 - 1000) / 256; TL0 (65535 - 1000) % 256;ET0 1;EA 1;TR0 1;
}void Service_Timer0() interrupt 1
{TH0 (65535 - 1000) / 256;TL0 (65535 - 1000) % 256;if(stat_go 0) {XBYTE[0x8000] 0xe7; return;} pwm; if(pwm pwm_duty) {XBYTE[0x8000] ~(0x01 stat);}else if(pwm 10){XBYTE[0x8000] 0xff;}else{XBYTE[0x8000] ~(0x01 stat);pwm 0;if(key_puse 0) {times;}}
}void LED_Control()
{if(times 5) {times 0;if(led_go 0) {pwm_duty pwm_duty 1;if(pwm_duty 11){pwm_duty 10;led_go 1;}}else if(led_go 1) {pwm_duty pwm_duty - 1;if(pwm_duty 255){pwm_duty 0;led_go 0;if(stat_go 1) {stat;if(stat 8){stat 0;}}else if(stat_go 2) {stat--;if(stat 255){stat 7;}}}}}
}void Scan_Keys()
{if(S4 0){DelaySMG(100);if(S4 0){while(S4 0){key_puse 1;}key_puse 0;stat_go; if(stat_go 3){stat_go 1;}}}if(S7 0){DelaySMG(100);if(S7 0){while(S7 0){key_puse 1;Display_Info(stat 1, pwm_duty * 10);}key_puse 0;}}
}void Init_System()
{//XBYTE[0xA000] 0xff;XBYTE[0xA000] 0x00;XBYTE[0xE000] 0xff;XBYTE[0xC000] 0xff;Init_Timer0();
}main()
{Init_System();while(1){LED_Control();Scan_Keys();}
} 16.超声波测距模块的使用 1、超声波模块的 TX 引脚接到单片机的 P1.0 引脚RX 引脚接到单片机的 P1.1 引脚。 2、利用超声波传感器测量前端障碍物的距离测量结果 用厘米作为单位显示在数码管最右边 3 位。 3、测量距离最大约 100 厘米当障碍物超出测量范围或 前方无障碍物以“F”为标志显示在数码管最左边 1 位。 4、超声波传感器测距的工作原理 首先产生 8 个 40KHz 的超声波信号通过 TX 引脚发射出 去同时启动定时器计数计数脉冲接着等待超声波信号的返回。如果超声波传感器接收 到反射回来的信号则 RX 引脚变为低电平这时候停止定时器读取计数脉冲个数计算 超声波发射出去到反射回来的时间长度 T。最后根据公式L V*T/2,计算距离。 其中 V 为 20 摄氏度时的声速其值约为344 米/秒。 #include reg52.h
#include intrins.hsbit TX P1^0;
sbit RX P1^1;unsigned char code SMG_DuanMa[]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf};
unsigned int distance 0;
void SelectHC573(unsigned char channel)
{switch(channel){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;case 0: P2 (P2 0x1f) | 0x00;break;}
}void InitSystem()
{SelectHC573(5);P0 0x00;SelectHC573(4);P0 0xff;SelectHC573(0);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{SelectHC573(7);P0 0xff;SelectHC573(6);P0 0x01 pos;SelectHC573(7);P0 dat;SelectHC573(0);
}void DelaySMG(unsigned int t)
{while(t--);
}void DisplaySMG()
{if(distance 999){DisplaySMG_Bit(0,SMG_DuanMa[15]);DelaySMG(500);}else{DisplaySMG_Bit(5,SMG_DuanMa[distance / 100]);DelaySMG(500);DisplaySMG_Bit(6,SMG_DuanMa[distance / 10 % 10]);DelaySMG(500);DisplaySMG_Bit(7,SMG_DuanMa[distance % 10]);DelaySMG(500); }
}
void Delay_12us()
{unsigned char i;_nop_();_nop_();i 33;while (--i);
}
void SendWave()
{unsigned char j0;for(j0;j8;j){TX 1;Delay_12us();TX0;Delay_12us();}
}
void MeasureDistance()
{unsigned int time0;TMOD0x00;TH10;TL10;SendWave();TR11;while((RX1)(TF10));TR10;if(TF10){timeTH1;time(time8)|TL1;distancetime*0.0172;}else{TF10;distance999;}}void Delay(unsigned char n)
{while(n--){DisplaySMG();}}void main()
{InitSystem();while(1){MeasureDistance();Delay(5);}
} ——————————————————分界线———————————————— ░░░░░░░░░▄▄ ░░░░░░░░░█░█ ░░░░░░░░░█░█ ░░░░░░░░█░░█ ░░░░░░░█░░░█ █████▄▄█░░░████ ▓▓▓▓█░░░░░░░░░░░░█ ▓▓▓▓█░░░░░░░░░░░░█ ▓▓▓▓█░░░░░░░░░░░░█ ▓▓▓▓█░░░░░░░░░░░░█ ▓▓▓▓█░░░░░░░░░░░░█ ▓▓▓▓█████░░░░░░░░ ████▀░░░▀▀██████▀ ------------------------------------------- To Be Continue