2024-09-01
售卖作品
00

在这里插入图片描述

在这里插入图片描述

main.c

c
#include<reg52.h> #include<intrins.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include "lcd1602.h" #define uchar unsigned char #define uint unsigned int #define u8 unsigned char #define u16 unsigned int //以下是C调低音的音频宏定义 #define L1 262 //将"L1"宏定义为低音"1"的频率262Hz 时间是1/262=3826/2 us 取半周期 #define L2 286 //将"L2"宏定义为低音"2"的频率286Hz #define L3 311 //将"L3"宏定义为低音"3"的频率311Hz #define L4 349 //将"L4"宏定义为低音"4"的频率349Hz #define L5 392 //将"L5"宏定义为低音"5"的频率392Hz #define L6 440 //将"l_a"宏定义为低音"6"的频率440Hz #define L7 494 //将"L7"宏定义为低音"7"的频率494Hz //以下是C调中音的音频宏定义 #define Z1 523 //将"Z1"宏定义为中音"1"的频率523Hz #define Z2 587 //将"Z2"宏定义为中音"2"的频率587Hz #define Z3 659 //将"Z3"宏定义为中音"3"的频率659Hz #define Z4 698 //将"Z4"宏定义为中音"4"的频率698Hz #define Z5 784 //将"Z5"宏定义为中音"5"的频率784Hz #define Z6 880 //将"Z6"宏定义为中音"6"的频率880Hz #define Z7 987 //将"Z7"宏定义为中音"7"的频率523H //以下是C调高音的音频宏定义 #define H1 1046 //将"H1"宏定义为高音"1"的频率1046Hz #define H2 1174 //将"H2"宏定义为高音"2"的频率1174Hz #define H3 1318 //将"H3"宏定义为高音"3"的频率1318Hz #define H4 1396 //将"H4"宏定义为高音"4"的频率1396Hz #define H5 1567 //将"H5"宏定义为高音"5"的频率1567Hz #define H6 1760 //将"H6"宏定义为高音"6"的频率1760Hz #define H7 1975 //将"H7"宏定义为高音"7"的频率1975Hz /* ****************************************** */ // ******** 硬件端口定义 /* ****************************************** */ sbit sound = P1 ^ 4; //蜂鸣器 sbit KAISHI = P1 ^ 0; //开始 sbit ZANTING = P1 ^ 1; //暂停 sbit PRE_KEY = P1 ^ 2; //上一首 sbit NEXT_KEY = P1 ^ 3; //下一首 sbit yianjian = P1 ^ 5; //1 sbit eranjian = P1 ^ 6; //1 sbit sananjian = P1 ^ 7; //1 /* ****************************************** */ // ******** 程序变量定义 /* ****************************************** */ unsigned int C; //储存定时器的定时常数 unsigned char u, t; //音乐所用的变量 unsigned char velocity = 60; //控制节拍使用的 这里100表示一个拍子100ms unsigned char press_key = 0; //按键 按下后会改变数值 初始值为0 unsigned char open_flag = 1; //暂停时为0 播放时为1 unsigned char music_crr = 0; //当前是播放哪一首音乐 可以为0 1 2 分别是是三首歌 char rtc_hour = 0; char rtc_min = 0; char rtc_sec = 0; char num2 = 0; /* 计数 */ /* ****************************************** */ // ******** 音乐0 天空之城 /* ****************************************** */ //以下是《天空之城》简谱 //每行对应一小节音符 unsigned int code music0[]= { Z6,Z7,/**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1,/**/Z5,Z3,Z3, /**/Z4,Z3,Z4,H1, Z3,H1,H1,H1,/**/Z7,Z4,Z4,Z7,/**/Z7,Z6,Z7, /**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1, Z5, Z3,/**/Z4,H1,Z7,H1,/**/H2,H2,H2,H1,/**/H1,Z6,Z7,Z5,/**/Z6,H1,H2, /**/H3,H2,H3,H5, H2,Z5,Z5, /**/H1,Z7,H1,H3,/**/H3, /**/Z6,H1,Z7,H2,/**/H1,Z5,Z5, /**/H4,H3,H2,H1, H3, /**/Z3,H3, /**/H6,H5,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,H5,/**/H3,H3, H6,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,Z7,/**/Z6,Z6,Z7, /**/Z6,0xff}; //以0xff作为音符的结束标志 //以下是简谱中每个音符的节拍 //"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位 unsigned char code music0_JP[ ]= { 4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,4,12, 20,4,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, 32, 4, /**/8,4,6,8, /**/4,4,4,16, /**/8,4,6,8, /**/24,4,4, /**/12,4,8,8, 24,4,4, /**/4,4,8,8, /**/32, /**/4,8,8,6, /**/12,4,16, /**/8,8,8,8, 30, /**/20,8, /**/16,8,8, /**/4,4,16,8, /**/8,4,4,8, /**/20,8, 16,16, /**/4,20,8, /**/8,4,4,8, /**/20,4,4,8,8, /**/8}; /* ****************************************** */ // ******** 音乐2 /* ****************************************** */ unsigned int code music1[]= { Z3,Z3,Z5,Z6,H1,H1,Z6, Z5,Z5,Z6,Z5, Z3,Z3,Z5,Z6,H1,H1,Z6, Z5,Z5,Z6,Z5, Z5,Z5,Z5,Z3,Z5, Z6,Z6,Z5, Z3,Z2,Z3,Z5,Z3,Z2, Z1,Z1,Z2,Z1,0xff}; //以0xff作为音符的结束标志 //以下是简谱中每个音符的节拍 //"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位 unsigned char code music1_JP[ ]= { 16,8,8,8,8,8,8, 16,8,8,32, 16,8,8,8,8,8,8, 16,8,8,32, 16,16,16,8,8, 16,16,32, 16,8,8,16,8,8, 16,8,8,32,1,8,8}; /* ****************************************** */ // ******** 音乐3 小星星 /* ****************************************** */ unsigned int code music2[]= { H3,H3,H3,H2,H1,H2,H5,H5,H1,H1,H1,H1,Z6, Z7,H3,H3,Z5,Z6,H6,H5,H4,H3,H2,H1,H1, Z6,H1,H2,H5,H5,H2,H1,H2,H2,Z1,H3,H3, H3,H2,H1,H2,H5,H5,H1,H1,H1,H1,Z6,Z7, H3,H3,Z5,Z6,H6,H5,H4, H3,H2,H1,H1,Z6,H1,H2,H5,H5,Z5,H2,H1, 0xff}; //以0xff作为音符的结束标志 //以下是简谱中每个音符的节拍 //"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位 unsigned char code music2_JP[ ]= { 8,2,2,2,2,4,4,8, 8,2,2,2,2, 4,4,4,4,8,4,2,2,4,2,2,8, 2,2,2,2,2,2,2,2,8,8,8,2,2,2,2,4,4,8,8,2,2,2,2,4,4,4,4,8,4,2,2, 8,2,2,4,2,2,2,2,2,2,4,12,8,8 }; /* ****************************************** */ // ******** 延时1ms 用于一般延时 /* ****************************************** */ void delay(uint z) { uint x; while (z--) { for (x = 125; x > 0; x--) ; } } /* ****************************************** */ // ******** 延时100ms 控制音乐节拍 /* ****************************************** */ void delay1() { uint i, j; for (i = 0; i < velocity; i++) for (j = 0; j < 125; j++) ; } /* ****************************************** */ // ******** 定时器初始化函数 用了定时器1 /* ****************************************** */ void init_timer(void) { EA = 1; //开总中断 ET1 = 1; //定时器T1中断允许 TMOD &= 0x0f; TMOD |= 0x00; // 使用定时器T1的模式1(13位计数器) TR1 = 1; TMOD |= 0x01; // 使用定时器T1的模式1(13位计数器) TR0 = 1; ET0 = 1; //定时器T1中断允许 } /* ****************************************** */ // ******** 按键扫描 返回值 1 2 3 4 5 代表五个按键 /* ****************************************** */ unsigned char ScanKey(void) { if (KAISHI == 0) //是否按下 { delay(1); //延时防止电平抖动 if (KAISHI == 0) { while (KAISHI == 0) ; //等待松开 return 1; } } if (ZANTING == 0) { delay(1); if (ZANTING == 0) { while (ZANTING == 0) ; return 2; } } if (PRE_KEY == 0) { delay(1); if (PRE_KEY == 0) { while (PRE_KEY == 0) ; return 3; } } if (NEXT_KEY == 0) { delay(1); if (NEXT_KEY == 0) { while (NEXT_KEY == 0) ; return 4; } } if (yianjian == 0)//选择第1首歌的按键按下 { delay(1); if (yianjian == 0) { while (yianjian == 0) ; return 5; } } if (eranjian == 0) //选择第二首歌的按键按下 { delay(1); if (eranjian == 0) { while (eranjian == 0) ; return 6; } } if (sananjian == 0)//选择第3首歌的按键按下 { delay(1); if (sananjian == 0) { while (sananjian == 0) ; return 7; } } return 0; } /* ****************************************** */ // ******** 处理按键 按下按键后 相应变量改变 /* ****************************************** */ void delay_key(void) { if (press_key == 1) //开始 { open_flag = 1; //开始 press_key = 0; } if (press_key == 2) //暂停 { open_flag = 0; //暂停 press_key = 0; } if (press_key == 3) //上一首 { press_key = 0; if (music_crr > 0) { music_crr = (music_crr - 1) % 3; } else { music_crr = 2; //如果是第0首歌 那么按上一首就是第2首 } LCD_write_char(9,0,music_crr+'1');//显示歌曲号 rtc_hour=0;rtc_min=0; rtc_sec=0; } if (press_key == 4) //下一首 { press_key = 0; music_crr = (music_crr + 1) % 3; LCD_write_char(9,0,music_crr+'1'); //显示歌曲号 rtc_hour=0;rtc_min=0; rtc_sec=0; } if (press_key == 5) //1 { press_key = 0; music_crr=0; LCD_write_char(9,0,music_crr+'1'); //显示歌曲号 rtc_hour=0;rtc_min=0; rtc_sec=0; open_flag = 1; //开始 } if (press_key == 6) //2 { press_key = 0; music_crr=1; LCD_write_char(9,0,music_crr+'1'); //显示歌曲号 rtc_hour=0;rtc_min=0; rtc_sec=0; open_flag = 1; //开始 } if (press_key == 7) //3 { press_key = 0; music_crr=2; LCD_write_char(9,0,music_crr+'1'); //显示歌曲号 rtc_hour=0;rtc_min=0; rtc_sec=0; open_flag = 1; //开始 } if (open_flag == 1) { TR0=1; }else { TR0=0; } LCD_dis_TIME( 6, 1, rtc_hour, rtc_min, rtc_sec ); } uint changdu = 0; /* ****************************************** */ // ******** 主函数 程序逻辑 /* ****************************************** */ void main() { LCD_init(); LCD_write_str(0,0," WELCOME!"); delay(1000); LCD_write_str(0,0,"Playing: "); LCD_write_char(9,0,'1'); LCD_write_str(0,1,"Time:"); LCD_dis_TIME( 6, 1, rtc_hour, rtc_min, rtc_sec ); init_timer(); TR1 = 0; //关闭定时器 sound = 0; //关闭蜂鸣器 open_flag = 0; //关闭音乐 TR0 = 0; //关闭定时器 LCD_dis_TIME( 6, 1, rtc_hour, rtc_min, rtc_sec ); while (1) { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 if (music_crr == 0 && open_flag == 1) { u = 0; //从第1个音符f[0]开始播放 changdu = sizeof(music0); while (music0[u] != 0xff) //只要没有读到结束标志就继续播放 { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 if (music_crr != 0) //切换音乐 { init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 break; } if (open_flag == 0) //如果暂停音乐 { while (open_flag == 0) { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 } } C = 460830 / music0[u]; TH1 = (8192 - C) / 32; //可证明这是13位计数器TH0高8位的赋初值方法 5 TL1 = (8192 - C) % 32; //可证明这是13位计数器TL0低5位的赋初值方法 TR1 = 1; //启动定时器T0 changdu--; for (t = 0; t < music0_JP[u]; t++) //控制节拍数 delay1(); //延时1个节拍单位 TR1 = 0; //关闭定时器T1 u++; //播放下一个音符 } init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 } if (music_crr == 1 && open_flag == 1) { u = 0; //从第1个音符f[0]开始播放 changdu = sizeof(music1); while (music1[u] != 0xff) //只要没有读到结束标志就继续播放 { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 if (music_crr != 1) //切换音乐 { init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 break; } if (open_flag == 0) //如果暂停音乐 { while (open_flag == 0) { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 } } C = 460830 / music1[u]; TH1 = (8192 - C) / 32; //可证明这是13位计数器TH0高8位的赋初值方法 5 TL1 = (8192 - C) % 32; //可证明这是13位计数器TL0低5位的赋初值方法 TR1 = 1; //启动定时器T0 changdu--; for (t = 0; t < music1_JP[u]; t++) //控制节拍数 delay1(); //延时1个节拍单位 TR1 = 0; //关闭定时器T1 u++; //播放下一个音符 } init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 } if (music_crr == 2 && open_flag == 1) { u = 0; //从第1个音符f[0]开始播放 changdu = sizeof(music2); while (music2[u] != 0xff) //只要没有读到结束标志就继续播放 { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 if (music_crr != 2) //切换音乐 { init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 break; } if (open_flag == 0) //如果暂停音乐 { while (open_flag == 0) { press_key = ScanKey(); //获取按下的键 delay_key(); //将按下的键值传入处理函数 改变状态变量 } } C = 460830 / music2[u]; TH1 = (8192 - C) / 32; //可证明这是13位计数器TH0高8位的赋初值方法 5 TL1 = (8192 - C) % 32; //可证明这是13位计数器TL0低5位的赋初值方法 TR1 = 1; //启动定时器T0 changdu--; for (t = 0; t < music2_JP[u] / 2; t++) //控制节拍数 delay1(); //延时1个节拍单位 TR1 = 0; //关闭定时器T1 u++; //播放下一个音符 } init_timer(); TR1 = 0; //关闭定时器 sound = 1; //关闭蜂鸣器 } } } void Time1(void) interrupt 3 //T1定时器的中断等级要注意 是3 { sound=!sound; //将P3.7引脚输出电平取反,形成方波 TH1=(8192-C)/32;//可证明这是13位计数器TH0高8位的赋初值方法 TL1=(8192-C)%32;//可证明这是13位计数器TL0低5位的赋初值方法 } void Time0(void) interrupt 1 //T1定时器的中断等级要注意 是3 { TH0=(65535-50000)/255; //可证明这是13位计数器TH0高8位的赋初值方法 TL0=(65535-50000)%255;//可证明这是13位计数器TL0低5位的赋初值方法 num2++; if ( num2 == 20 ) { num2 = 0; rtc_sec++; if ( rtc_sec == 60 ) { rtc_sec = 0; rtc_min++; if ( rtc_min == 60 ) { rtc_min = 0; rtc_hour++; if ( rtc_hour == 24 ) { rtc_hour = 0; } } } } }

lcd1602.h

c
#include <reg52.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* LCD_init(); LCD_write_str(1,1,"2223123"); */ sbit lcd_rs=P2^5; sbit lcd_rw=P2^6; sbit lcd_en=P2^7; #define DataPort P0 #define RS_CLR lcd_rs=0 #define RS_SET lcd_rs=1 #define RW_CLR lcd_rw=0 #define EN_CLR lcd_en=0 #define EN_SET lcd_en=1 void delay_lcd_ms(unsigned int a) { unsigned int i, j; for (i = a; i > 0; i--) for (j = 100; j > 0; j--) ; } //*********************************************************************** // 显示屏命令写入函数 //*********************************************************************** void LCD_write_com(unsigned char com) { RS_CLR; RW_CLR; EN_SET; DataPort = com; //命令写入端口 delay_lcd_ms(5); EN_CLR; } //*********************************************************************** // 显示屏数据写入函数 //*********************************************************************** void LCD_write_data(unsigned char dataa) { RS_SET; RW_CLR; EN_SET; DataPort = dataa; //数据写入端口 delay_lcd_ms(5); EN_CLR; } //*********************************************************************** // 显示屏单字符写入函数 //*********************************************************************** void LCD_write_char(unsigned char x,unsigned char y,unsigned char dataa) { if (y == 0) { LCD_write_com(0x80 + x); //第一行显示 } else { LCD_write_com(0xC0 + x); //第二行显示 } LCD_write_data( dataa); } //*********************************************************************** // 显示屏字符串写入函数 //*********************************************************************** void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s) { EA=0; if (y == 0) { LCD_write_com(0x80 + x); //第一行显示 } else { LCD_write_com(0xC0 + x); //第二行显示 } while (*s) { LCD_write_data( *s); s ++; } EA=1; } //*********************************************************************** // 显示一个数字 传入坐标和数值 //*********************************************************************** void LCD_dis_TIME(unsigned char x,unsigned char y, int hour,int min,int sec) { char disp[10]; memset(disp,0,10); sprintf(disp,"%02d:%02d:%02d",hour,min,sec); LCD_write_str(x,y,disp); } //*********************************************************************** // 显示屏初始化函数 //*********************************************************************** void LCD_init(void) { LCD_write_com(0x38); //显示模式设置 delay_lcd_ms(5); LCD_write_com(0x38); //显示模式设置 delay_lcd_ms(5); LCD_write_com(0x38); //显示模式设置 delay_lcd_ms(5); LCD_write_com(0x38); //显示模式设置 delay_lcd_ms(5); LCD_write_com(0x08); //显示关闭 delay_lcd_ms(5); LCD_write_com(0x01); //显示清屏 delay_lcd_ms(5); LCD_write_com(0x06); //显示光标移动设置 delay_lcd_ms(5); LCD_write_com(0x0C); //显示开及光标设置 delay_lcd_ms(5); }
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!