目录
七、矩阵键盘
八、定时器和中断
九、串口通信
十、LED点阵屏
十一、DS1302实时时钟
十二、蜂鸣器
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
#include <REGX52.H>
#include "Delay.h"
/*** @brief 矩阵键盘读取按键键码* @param 无* @retval KeyNumber 按下按键的键码值如果按键按下不放,程序会停留在此函数,松手的瞬间,返回键码,没有按键按下时,返回零。*/
unsigned char MatrixKey(){unsigned char KeyNumber=0;// 按列扫描// 第一列P1=0xFF;P1_3=0;if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}// 第二列P1=0xFF;P1_2=0;if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}// 第三列P1=0xFF;P1_1=0;if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}// 第四列P1=0xFF;P1_0=0;if(P1_7==0){ Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}if(P1_6==0){ Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}if(P1_5==0){ Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}if(P1_4==0){ Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}return KeyNumber;
}
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main(){LCD_Init();LCD_ShowString(1,1,"Which One?");while(1){KeyNum=MatrixKey();if(KeyNum){ // 不加if,KeyNum会马上刷新为0LCD_ShowNum(2,1,KeyNum,2);}}
}
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Password,Count;
void main(){LCD_Init();LCD_ShowString(1,1,"Password:");while(1){KeyNum=MatrixKey();if(KeyNum){ // 不加if,KeyNum会马上刷新为0if(KeyNum<=10){ // 如果是s1~s10按下,输入密码if(Count<4){ // 限制密码位数Password*=10; // 密码左移一位Password+=KeyNum%10; // 将10转化为0,获得一位密码Count++; // 记录密码位数}}LCD_ShowNum(2,1,Password,4); // 更新显示}if(KeyNum==11){ // s11按下,确认if(Password==1234){ // 判断密码LCD_ShowString(1,11,"TRUE"); // 密码正确Password=0; // 密码清零Count=0; // 计次清零LCD_ShowNum(2,1,Password,4); // 更新显示}else{LCD_ShowString(1,11,"ERR"); // 密码错误Password=0; // 密码清零Count=0; // 计次清零LCD_ShowNum(2,1,Password,4); // 更新显示}}if(KeyNum==12){ // s12按下,取消Password=0; // 密码清零Count=0; // 计次清零LCD_ShowNum(2,1,Password,4); // 更新显示}}
}
//定时器0初始化
void Timer0Init(){//TMOD=0x01; // 0000 0001 这样赋值在同时使用定时器1和定时器0时可能会产生冲突TMOD&=0xF0; // 把TMOD低四位清零,高四位不变TMOD|=TMOD|0x01; // 把TMOD最低位置1,高四位不变TF0=0; // 中断溢出标志位TR0=1; // 开启定时器// 初始化计数器TH0=64535/256; // 取高位TL0=64535%256+1; // 取低位// 配置中断ET0=1; // 允许中断EA=1; // 允许总中断PT0=0; // 中断优先级
}
void Timer0Init(void) //1毫秒@12.000MHz
{TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时// 配置中断ET0=1; // 允许中断EA=1; // 允许总中断PT0=0; // 中断优先级
}
#include <REGX52.H>
/*** @brief 定时器0初始化,1毫秒@12.000MHz* @param 无* @retval 无*/
void Timer0Init(void) //1毫秒@12.000MHz
{TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时// 配置中断ET0=1;EA=1; PT0=0;
}
/* 定时器中断函数模板
void Timer0_Routine() interrupt 1{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=1000){T0Count=0;P2_0=~P2_0;}
}
*/
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init(void);
#endif
#include <REGX52.H>
#include "Delay.h"
/*** @brief 获取独立按键键码* @param 无* @retval 按下按键的键码,范围:0~4,无按键按下时,返回0*/
unsigned char Key(){unsigned char KeyNumber=0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}return KeyNumber;
}
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <intrins.h> // 引入_crol_()和_cror_()循环移位函数
unsigned char KeyNum,LEDMode;
void main(){Timer0Init(); // 定时器0初始化P2=0xFE; // 初始化LEDwhile(1){ // 每当定时器溢出,就跳转执行中断函数KeyNum=Key();if(KeyNum){if(KeyNum==1){LEDMode++;if(LEDMode>=2) LEDMode=0; // LEDMode只在0和1变化}}}
}
// 中断函数
void Timer0_Routine() interrupt 1{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=500){ // 每隔0.5ms让LED移动T0Count=0;if(LEDMode==0)P2=_crol_(P2,1); // P2左移1位else P2=_cror_(P2,1); // P2右移1位}
}
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
unsigned char Sec=55,Min=59,Hour=23;
void main(){LCD_Init();Timer0Init();LCD_ShowString(1,1,"Clock:");LCD_ShowString(2,1," : :");while(1){LCD_ShowNum(2,1,Hour,2); // 小时LCD_ShowNum(2,4,Min,2); // 分钟LCD_ShowNum(2,7,Sec,2); // 秒}
}
// 中断函数
void Timer0_Routine() interrupt 1{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=1000){T0Count=0;Sec++;if(Sec>=60){Sec=0;Min++;if(Min>=60){Min=0;Hour++;if(Hour>=24) Hour=0;}}}
}
// 串口初始化
void UART_Init(){ // 4800bps@12.000MHzPCON |= 0x80;SCON = 0x40;// 配置定时器1(只允许使用定时器1)TMOD &= 0x0F; //设置定时器模式TMOD |= 0x20; //设置定时器模式TL1 = 0xF3; //设置定时初值TH1 = 0xF3; //设置定时初值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1
}
#include <REGX52.H>
/*** @brief 串口初始化,4800bps@12.000MHz* @param 无* @retval 无*/
void UART_Init(){PCON |= 0x80;SCON = 0x50;// 配置定时器1(只允许使用定时器1)TMOD &= 0x0F; //设置定时器模式TMOD |= 0x20; //设置定时器模式TL1 = 0xF3; //设置定时初值TH1 = 0xF3; //设置定时初值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1
}
/*** @brief 串口发送一个字节数据* @param Byte 要发送的一个字节数据* @retval 无*/
void UART_SendByte(unsigned char Byte){SBUF=Byte; // 串口缓冲寄存器while(TI==0); // 检测是否完成。机械控制为1,即TI为1时发送完成。TI=0; // 软件复位
}
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main(){UART_Init();while(1){UART_SendByte(Sec);Sec++;Delay(1000);}
}
void UART_Init(){PCON |= 0x80;SCON = 0x50;// 配置定时器1(只允许使用定时器1)TMOD &= 0x0F; //设置定时器模式TMOD |= 0x20; //设置定时器模式TL1 = 0xF3; //设置定时初值TH1 = 0xF3; //设置定时初值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1// 配置中断EA=1; // 启动所有中断ES=1;// 启动串口中断
}
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main(){UART_Init();while(1){}
}
void UART_Rountine() interrupt 4{ // 当单片机串口接收到数据时,该中断函数会执行if(RI==1){ // 接收中断请求标志位,将发送和接收区分开P2=~SBUF;UART_SendByte(SBUF); // 将单片机收到的数据发送到电脑显示RI=0; // 软件复位}
}
#include <REGX52.H>
#include "Delay.h"
sbit RCK=P3^5; // RCLK寄存器时钟
sbit SCK=P3^6; // SRCLK串行时钟
sbit SER=P3^4; // SER串行数据
#define MATRIX_LED_PORT P0
void MatrixLED_Init(){ // 初始化74HC595SCK=0;RCK=0;
}
void _74HC595_WriteByte(unsigned char Byte){ // 控制行unsigned char i;for(i=0;i<8;i++){ // 将8位数据放入移位寄存器SER=Byte&(0x80>>i); // 非0赋1SCK=1; // 移位SCK=0;}RCK=1; // 将8位数据输出RCK=0;
}
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line){_74HC595_WriteByte(Line); // 第几行亮MATRIX_LED_PORT=~(0x80>>Column); // 第几列亮,0选中Delay(1); // 消影MATRIX_LED_PORT=0xFF;
}
void main(){MatrixLED_Init();while(1){MatrixLED_ShowColumn(0,0x3C);MatrixLED_ShowColumn(1,0x42);MatrixLED_ShowColumn(2,0xA9);MatrixLED_ShowColumn(3,0x85);MatrixLED_ShowColumn(4,0x85);MatrixLED_ShowColumn(5,0xA9);MatrixLED_ShowColumn(6,0x42);MatrixLED_ShowColumn(7,0x3C);}
}
#include <REGX52.H>
#include "Delay.h"
sbit RCK=P3^5; // RCLK寄存器时钟
sbit SCK=P3^6; // SRCLK串行时钟
sbit SER=P3^4; // SER串行数据
#define MATRIX_LED_PORT P0
/*** @brief LED点阵屏初始化* @param 无* @retval 无*/
void MatrixLED_Init(){ // 初始化74HC595SCK=0;RCK=0;
}
/*** @brief 74HC595写入一个字节* @param 要写入的字节* @retval 无*/
void _74HC595_WriteByte(unsigned char Byte){ // 控制行unsigned char i;for(i=0;i<8;i++){ // 将8位数据放入移位寄存器SER=Byte&(0x80>>i); // 非0赋1SCK=1; // 移位SCK=0;}RCK=1; // 将8位数据输出RCK=0;
}
/*** @brief LED点阵屏显示一列数据* @param Column 要选择的列,范围:0~7,0在最左边* @param Line 选择列显示的数据,高位在上,1为亮,0为灭* @retval 无*/
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line){_74HC595_WriteByte(Line); // 第几行亮MATRIX_LED_PORT=~(0x80>>Column); // 第几列亮,0选中Delay(1); // 消影MATRIX_LED_PORT=0xFF;
}
#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__
void MatrixLED_Init();
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Line);
#endif
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
unsigned char code Animation[]={ // code将数组放入flash中0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 为了让动画流畅,开头让动画流水出现0xFF,0x08,0x08,0x08,0xFF,0x00,0x0E,0x15,0x15,0x0C,0x00,0x7E,0x01,0x01,0x02,0x00,0x7E,0x01,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,0x00,0x7D,0x00,0x7D,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 显示完空的8列,再显示新的,才不会扰乱前面的显示
};
void main(){unsigned char i,offset,Count;MatrixLED_Init();while(1){for(i=0;i<8;i++){MatrixLED_ShowColumn(i,Animation[i+offset]);}Count++;if(Count>10){ // 一帧扫描十遍,不能用延时函数,会显得动画不流畅Count=0;offset++;if(offset>40) offset=0;}}
}
#include <REGX52.H>
sbit DS1302_SCLK=P3^6; // 串行时钟
sbit DS1302_IO=P3^4; // 数据输入/输出
sbit DS1302_CE=P3^5; // 芯片使能
// 写入地址
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
char DS1302_TIME[]={23,8,11,13,59,55,5};
/*** @brief 初始化DS1302时钟* @param 无* @retval 无*/
void DS1302_Init(void){DS1302_CE=0;DS1302_SCLK=0;
}
/*** @brief 向DS1302中写入一个字节数据* @param Command 要写入的命令* @param Data 要写入的数据* @retval 无*/
void DS1302_WriteByte(unsigned char Command,Data){unsigned char i;DS1302_CE=1;// 输入控制位for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);DS1302_SCLK=1; // 时序,一个上升下降沿读取IO口的一位DS1302_SCLK=0;}// 输入数据for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1; // 时序DS1302_SCLK=0;}DS1302_CE=0;
}
/*** @brief 从DS1302读出一个字节数据* @param Command 要写入的命令* @retval Data 读出的一个字节数据*/
unsigned char DS1302_ReadByte(unsigned char Command){unsigned char i,Data=0x00;Command|=0x01; // 将写的地址改为读的地址DS1302_CE=1;// 输入控制位for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);DS1302_SCLK=0; // 时序DS1302_SCLK=1;}// 读取数据for(i=0;i<8;i++){DS1302_SCLK=1;DS1302_SCLK=0;if(DS1302_IO){ Data|=(0x01<<i);} // 将对应位置1}DS1302_CE=0;DS1302_IO=0;return Data;
}
/*** @brief 使用数组设置时间* @param 无* @retval 无*/
void DS1302_SetTime(void){DS1302_WriteByte(DS1302_WP,0x00); // 关闭芯片写保护DS1302_WriteByte(DS1302_YEAR,DS1302_TIME[0]/10*16+DS1302_TIME[0]%10); // 十进制转BCDDS1302_WriteByte(DS1302_MONTH,DS1302_TIME[1]/10*16+DS1302_TIME[1]%10);DS1302_WriteByte(DS1302_DATE,DS1302_TIME[2]/10*16+DS1302_TIME[2]%10);DS1302_WriteByte(DS1302_HOUR,DS1302_TIME[3]/10*16+DS1302_TIME[3]%10);DS1302_WriteByte(DS1302_MINUTE,DS1302_TIME[4]/10*16+DS1302_TIME[4]%10);DS1302_WriteByte(DS1302_SECOND,DS1302_TIME[5]/10*16+DS1302_TIME[5]%10);DS1302_WriteByte(DS1302_DAY,DS1302_TIME[6]/10*16+DS1302_TIME[6]%10);DS1302_WriteByte(DS1302_WP,0x80); // 打开芯片写保护
}
/*** @brief 读取时间到数组* @param 无* @retval 无*/
void DS1302_ReadTime(void){unsigned char Temp;Temp=DS1302_ReadByte(DS1302_YEAR);DS1302_TIME[0]=Temp/16*10+Temp%16; // BCD转十进制Temp=DS1302_ReadByte(DS1302_MONTH);DS1302_TIME[1]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_DATE);DS1302_TIME[2]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_HOUR);DS1302_TIME[3]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_MINUTE);DS1302_TIME[4]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_SECOND);DS1302_TIME[5]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_DAY);DS1302_TIME[6]=Temp/16*10+Temp%16;
}
#ifndef __DS1302_H__
#define __DS1302_H__
void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_ReadTime(void);
void DS1302_SetTime(void);
extern char DS1302_TIME[];
#endif
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
void main(){LCD_Init();DS1302_Init();LCD_ShowString(1,1," / / ( )");LCD_ShowString(2,1," : :");DS1302_SetTime();while(1){DS1302_ReadTime();LCD_ShowNum(1,1,DS1302_TIME[0],2);LCD_ShowNum(1,4,DS1302_TIME[1],2);LCD_ShowNum(1,7,DS1302_TIME[2],2);LCD_ShowNum(1,10,DS1302_TIME[6],1); // 星期LCD_ShowNum(2,1,DS1302_TIME[3],2);LCD_ShowNum(2,4,DS1302_TIME[4],2);LCD_ShowNum(2,7,DS1302_TIME[5],2);}
}
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
/*** @brief 显示时间* @param 无* @retval 无*/
void TimeShow(void){DS1302_ReadTime();LCD_ShowNum(1,1,DS1302_TIME[0],2);LCD_ShowNum(1,4,DS1302_TIME[1],2);LCD_ShowNum(1,7,DS1302_TIME[2],2);LCD_ShowNum(1,10,DS1302_TIME[6],1); // 星期LCD_ShowNum(2,1,DS1302_TIME[3],2);LCD_ShowNum(2,4,DS1302_TIME[4],2);LCD_ShowNum(2,7,DS1302_TIME[5],2);
}
/*** @brief 调节时间* @param 无* @retval 无*/
void TimeSet(void){if(KeyNum==2){ // 按键按键2选择要更新的位置TimeSetSelect++;TimeSetSelect%=7; // 越界清零}else if(KeyNum==3){ // 按键按键3数字加一DS1302_TIME[TimeSetSelect]++;// 上界判断if(DS1302_TIME[0]>99) DS1302_TIME[0]=0; // 年if(DS1302_TIME[1]>12) DS1302_TIME[1]=1; // 月// 日if(DS1302_TIME[1]==1 || DS1302_TIME[1]==3 || DS1302_TIME[1]==5 || DS1302_TIME[1]==7 ||DS1302_TIME[1]==8 || DS1302_TIME[1]==10 || DS1302_TIME[1]==12){if(DS1302_TIME[2]>31) DS1302_TIME[2]=1;}else if(DS1302_TIME[1]==4 || DS1302_TIME[1]==6 || DS1302_TIME[1]==9 || DS1302_TIME[1]==11){if(DS1302_TIME[2]>30) DS1302_TIME[2]=1;}else if(DS1302_TIME[1]==2){if(DS1302_TIME[0]%4==0 && DS1302_TIME[0]%100!=0){ // 闰年if(DS1302_TIME[2]>29) DS1302_TIME[2]=1;}else{if(DS1302_TIME[2]>28) DS1302_TIME[2]=1; // 平年}}if(DS1302_TIME[3]>23) DS1302_TIME[3]=0; // 时if(DS1302_TIME[4]>59) DS1302_TIME[4]=0; // 分if(DS1302_TIME[5]>59) DS1302_TIME[5]=0; // 秒if(DS1302_TIME[6]>7) DS1302_TIME[6]=1; // 星期}else if(KeyNum==4){ // 按键按键4数字减一DS1302_TIME[TimeSetSelect]--;// 下界判断if(DS1302_TIME[0]<0) DS1302_TIME[0]=99; // 年if(DS1302_TIME[1]<1) DS1302_TIME[1]=12; // 月// 日if(DS1302_TIME[1]==1 || DS1302_TIME[1]==3 || DS1302_TIME[1]==5 || DS1302_TIME[1]==7 ||DS1302_TIME[1]==8 || DS1302_TIME[1]==10 || DS1302_TIME[1]==12){if(DS1302_TIME[2]<1) DS1302_TIME[2]=31;if(DS1302_TIME[2]>31) DS1302_TIME[2]=1;}else if(DS1302_TIME[1]==4 || DS1302_TIME[1]==6 || DS1302_TIME[1]==9 || DS1302_TIME[1]==11){if(DS1302_TIME[2]<1) DS1302_TIME[2]=30;if(DS1302_TIME[2]>30) DS1302_TIME[2]=1;}else if(DS1302_TIME[1]==2){if(DS1302_TIME[0]%4==0 && DS1302_TIME[0]%100!=0){ // 闰年if(DS1302_TIME[2]<1) DS1302_TIME[2]=29;if(DS1302_TIME[2]>29) DS1302_TIME[2]=1;}else{if(DS1302_TIME[2]<1) DS1302_TIME[2]=28; // 平年if(DS1302_TIME[2]>28) DS1302_TIME[2]=1;}}if(DS1302_TIME[3]<0) DS1302_TIME[3]=23; // 时if(DS1302_TIME[4]<0) DS1302_TIME[4]=59; // 分if(DS1302_TIME[5]<0) DS1302_TIME[5]=59; // 秒if(DS1302_TIME[6]<1) DS1302_TIME[6]=7; // 星期}// 更新显示if(TimeSetSelect==0 && TimeSetFlashFlag==1) LCD_ShowString(1,1," ");else LCD_ShowNum(1,1,DS1302_TIME[0],2);if(TimeSetSelect==1 && TimeSetFlashFlag==1) LCD_ShowString(1,4," ");else LCD_ShowNum(1,4,DS1302_TIME[1],2);if(TimeSetSelect==2 && TimeSetFlashFlag==1) LCD_ShowString(1,7," ");else LCD_ShowNum(1,7,DS1302_TIME[2],2);if(TimeSetSelect==3 && TimeSetFlashFlag==1) LCD_ShowString(2,1," ");else LCD_ShowNum(2,1,DS1302_TIME[3],2);if(TimeSetSelect==4 && TimeSetFlashFlag==1) LCD_ShowString(2,4," ");else LCD_ShowNum(2,4,DS1302_TIME[4],2);if(TimeSetSelect==5 && TimeSetFlashFlag==1) LCD_ShowString(2,7," ");else LCD_ShowNum(2,7,DS1302_TIME[5],2);if(TimeSetSelect==6 && TimeSetFlashFlag==1) LCD_ShowString(1,10," ");else LCD_ShowNum(1,10,DS1302_TIME[6],1);LCD_ShowNum(2,10,TimeSetSelect,1);
}
void main(){LCD_Init();DS1302_Init();Timer0Init();LCD_ShowString(1,1," / / ( )");LCD_ShowString(2,1," : :");DS1302_SetTime();while(1){KeyNum=Key(); // 获取键码值if(KeyNum==1){ // 按下按键1修改/保存时间 if(MODE==0) {MODE=1;TimeSetSelect=0;}else if(MODE==1) {MODE=0;DS1302_SetTime();}}switch(MODE){case 0:TimeShow();break;case 1:TimeSet();break;}}
}
// 定时器0
void Timer0_Routine() interrupt 1{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=500){ // 5msT0Count=0;TimeSetFlashFlag=!TimeSetFlashFlag;}
}
for(i=0;i<500;i++){Buzzer=!Buzzer; // 蜂鸣器控制引脚Delay(1); // 每隔一毫秒翻转一次,周期为2毫秒,频率为500HZ
} // 以500HZ的频率响500ms
#include <REGX52.H>
#include <INTRINS.H>
// 蜂鸣器端口
sbit Buzzer=P2^5;
/*** @brief 蜂鸣器私有延时函数,延时500微秒* @param 无* @retval 无*/
void Buzzer_Delay500us() //@12.000MHz
{unsigned char i;_nop_(); // 延时一个机器周期i = 247;while (--i);
}
/*** @brief 让蜂鸣器以1000HZ的频率发声* @param ms 发声时长* @retval 无*/
void Buzzer_Time(unsigned int ms){unsigned int i;for(i=0;i<ms*2;i++){Buzzer=!Buzzer;Buzzer_Delay500us(); // 每隔500微秒翻转一次,周期为1毫秒,频率为1000HZ}
}
#ifndef __BUZZER_H__
#define __BUZZER_H__
void Buzzer_Time(unsigned int ms);
#endif
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Buzzer.h"
unsigned char KeyNum;
void main(){Nixie_Static(1,0);while(1){KeyNum=Key();if(KeyNum){Buzzer_Time(100); // 蜂鸣器发声100msNixie_Static(1,KeyNum); // 显示对应按键的键码}}
}
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"
sbit Buzzer=P2^5;
#define SPEED 500 //十六分音符时长
unsigned int FreqTable[]={ // 低中高音0, // 休止符63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283
};
unsigned char Music[]={13,4,13,4,20,4,20,4,22,4,22,4,20,8,0,2,18,4,18,4,17,4,17,4,15,4,15,4,13,8,0xFF, // 终止标志
};
unsigned char FreqSelect=0,MusicSelect=0;
void main(){Timer0Init();while(1){if(Music[MusicSelect]!=0xFF){FreqSelect=Music[MusicSelect];MusicSelect++;Delay(SPEED/4*Music[MusicSelect]);MusicSelect++;// 不让音符连在一起TR0=0;Delay(5);TR0=1;}else{TR0=0;while(1);}}
}
void Timer0_Routine() interrupt 1{ // 1ms执行一次,500HZif(FreqTable[FreqSelect]){TL0 = FreqTable[FreqSelect]%256; //设置定时初值TH0 = FreqTable[FreqSelect]/256; //设置定时初值Buzzer=!Buzzer;}
}
本文发布于:2024-01-29 09:52:51,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170649317414452.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |