2024-09-01
售卖作品
00

在这里插入图片描述

c
//键盘 //启动 停止 加速 减速 //紧急 -- 升高 降低 //模式 加时 加分 加秒 // -- 减时 减分 减秒 //启动就是开启跑步机 灯0打开 //停止关闭跑步机 灯0关闭 //加速就是加速跑步机 速度越快 灯0越来越亮 //减速就是减速跑步机 速度越慢 灯0越来越暗 距离会根据速度有换算 速度越快距离随时间变化越大 //紧急是紧急停止的意思 其实就是怕停止按键失效 紧急停止会关闭跑步机 //升高 就是升高跑步机坡度 就是灯1越亮 表示越高 实际跑步机会用舵机 和这个一样原理 //降低 就是降低跑步机坡度 //模式 就是进行模式切换的 按一下 进入倒计时模式 再按一下回到正计时模式 倒计时模式下可以设置倒计时时间 //后面这6个按键就是设置倒计时时间的 #include <reg52.h> #include <intrins.h> #include "lcd1602.h" #define uchar unsigned char #define uint unsigned int sbit ENA = P1 ^ 1; /* 使能 PWM 占空比越大 电机速度越快 接到灯上就是灯会越亮 */ sbit ENB = P1 ^ 0; /* 使能 PWM 占空比越大 电机速度越快 接到灯上就是灯会越亮 */ uchar pwm_count = 0; /* PWM计数 不用管 */ char ENA_PWM_data = 1; /* 0表示占空比0 10表示占空比百分之百 */ char ENB_PWM_data = 9; /* 0表示占空比0 10表示占空比百分之百 */ uchar open = 0; /* 是否打开 */ char rtc_hour = 0; char rtc_min = 0; char rtc_sec = 0; char num2 = 0; /* 计数 */ uchar time_count_mode = 0; /* 正计时 */ uint daojishi_shijiana = 0; void delay( uint z ) { uint x; while ( z-- ) { for ( x = 125; x > 0; x-- ) ; } } void init_timer( void ) { EA = 1; /* 开总中断 */ TMOD = 0x11; ET0 = 1; TR0 = 1; TH0 = (65536 - 50000) / 256; /* 计数初值重装载 */ TL0 = (65536 - 50000) % 256; ET1 = 1; TR1 = 1; TH1 = (65536 - 50000) / 256; TL1 = (65536 - 50000) % 256; } #define GPIO_KEY P3 unsigned char KeyValue = 0xff; /* 矩阵键盘扫描 电子琴 */ void ScanKey( void ) { char a = 0; GPIO_KEY = 0x0f; if ( GPIO_KEY != 0x0f ) /* 读取按键是否按下 */ { delay( 5 ); /* 延时10ms进行消抖 */ if ( GPIO_KEY != 0x0f ) /* 再次检测键盘是否按下 */ { /* 测试列 */ GPIO_KEY = 0X0F; switch ( GPIO_KEY ) { case (0X07): KeyValue = 0; break; case (0X0b): KeyValue = 1; break; case (0X0d): KeyValue = 2; break; case (0X0e): KeyValue = 3; break; } /* 测试行 */ GPIO_KEY = 0XF0; switch ( GPIO_KEY ) { case (0X70): KeyValue = KeyValue; break; case (0Xb0): KeyValue = KeyValue + 4; break; case (0Xd0): KeyValue = KeyValue + 8; break; case (0Xe0): KeyValue = KeyValue + 12; break; } while ( (a < 100) && (GPIO_KEY != 0xf0) ) /* 检测按键松手检测 */ { delay( 10 ); a++; } } } } /*按键处理 */ void KEY_CHULI( void ) { uchar map[]={3,7,11,15,2,6,10,14,1,5,9,13,0,4,8,12}; if ( KeyValue!= 0xff ) { KeyValue=map[KeyValue]; if ( KeyValue == 0 ) { open = 1; /* 启动 */ if ( time_count_mode == 1 ) { /* 倒计时 */ daojishi_shijiana = rtc_hour * 3600 + rtc_min * 60 + rtc_sec; } }else if ( KeyValue == 1 ) { open = 0; /* 停止 */ ENA = 1; }else if ( KeyValue == 2 ) { ENA_PWM_data++; /* 加速 */ if ( ENA_PWM_data == 11 ) ENA_PWM_data = 10; }else if ( KeyValue == 3 ) { ENA_PWM_data--; /*减速 */ if ( ENA_PWM_data == 0 ) ENA_PWM_data = 1; }else if ( KeyValue == 4 ) { open = 0; /*紧急停止 */ ENA = 1; }else if ( KeyValue == 6 ) { ENB_PWM_data++; /* 升高 */ if ( ENB_PWM_data == 11 ) ENB_PWM_data = 10; }else if ( KeyValue == 7 ) { ENB_PWM_data--; /*降低 */ if ( ENB_PWM_data == -1 ) ENB_PWM_data = 0; }else if ( KeyValue == 8 ) { /* 切换到倒计时模式 */ time_count_mode = !time_count_mode; /* 切换 */ open = 0; if ( time_count_mode == 0 ) { rtc_hour = 0; rtc_min = 0; rtc_sec = 0; }else{ rtc_hour = 0; rtc_min = 10; rtc_sec = 0; } } /* 倒计时下可以设置时间 */ if ( time_count_mode == 1 ) { if ( KeyValue == 9 ) { /* 加 时 */ rtc_hour++; if ( rtc_hour == 24 ) rtc_hour = 0; }else if ( KeyValue == 10 ) { /* 加 分 */ rtc_min++; if ( rtc_min == 60 ) rtc_min = 0; }else if ( KeyValue == 11 ) { /* 加秒 */ rtc_sec++; if ( rtc_sec == 60 ) rtc_sec = 0; }else if ( KeyValue == 13 ) { /* 减时 */ rtc_hour--; if ( rtc_hour == -1 ) rtc_hour = 23; }else if ( KeyValue == 14 ) { /* 减分 */ rtc_min--; if ( rtc_min == -1 ) rtc_min = 59; }else if ( KeyValue == 15 ) { /* 减秒 */ rtc_sec--; if ( rtc_sec == -1 ) rtc_sec = 59; } /* 倒计时 */ daojishi_shijiana = rtc_hour * 3600 + rtc_min * 60 + rtc_sec; } KeyValue = 0xff; /* 恢复按键状态 */ } } /* 刷新屏幕显示 */ void update( void ) { uint juli = 0; /* * 刷新 速度显示 显示在第一排 第一个位置 * ENA_PWM_data 就是速度 */ LCD_write_str( 0, 0, "A:" ); LCD_write_char( 2, 0, '0' + ENA_PWM_data / 10 ); LCD_write_char( 3, 0, '0' + ENA_PWM_data % 10 ); /* * 刷新 角度显示 显示在第一排 * ENB_PWM_data 就是角度 */ LCD_write_str( 5, 0, "B:" ); LCD_write_char( 7, 0, '0' + ENB_PWM_data / 10 ); LCD_write_char( 8, 0, '0' + ENB_PWM_data % 10 ); /* 模式 */ LCD_write_char( 10, 0, 'M' ); LCD_write_char( 11, 0, '0' + time_count_mode ); /* 0就是正计时 1就是倒计时 */ //此时跑步机状态 LCD_write_char( 13, 0, '0' + open ); /* 0没开 1开着的 */ /* 刷新时间 */ LCD_write_char( 0, 1, '0' + rtc_hour / 10 ); LCD_write_char( 1, 1, '0' + rtc_hour % 10 ); LCD_write_char( 2, 1, ':' ); LCD_write_char( 3, 1, '0' + rtc_min / 10 ); LCD_write_char( 4, 1, '0' + rtc_min % 10 ); LCD_write_char( 5, 1, ':' ); LCD_write_char( 6, 1, '0' + rtc_sec / 10 ); LCD_write_char( 7, 1, '0' + rtc_sec % 10 ); /* 刷新距离 */ if ( time_count_mode == 0 ) { juli = (uint) (rtc_hour * 3600 + rtc_min * 60 + rtc_sec) ; /* 1s 算走4.5m */ juli = (uint) (juli*4.5); }else{ juli = (uint) (rtc_hour * 3600 + rtc_min * 60 + rtc_sec) ; /* 1s 算走4.5m */ juli = (uint) (juli*4.5); juli = (uint) (daojishi_shijiana * 4.5 ) - juli; } LCD_write_char( 9, 1, '0' + juli / 10000 ); LCD_write_char( 10, 1, '0' + juli % 10000 / 1000 ); LCD_write_char( 11, 1, '0' + juli % 1000 / 100 ); LCD_write_char( 12, 1, '0' + juli % 100 / 10 ); LCD_write_char( 13, 1, '0' + juli % 10 ); LCD_write_char( 14, 1, 'm' ); } /* 主程序 */ void main() { init_timer(); LCD_init(); open = 0; ENA = 1; /* 关闭PWM */ ENA_PWM_data = 5; /* 0表示占空比0 10表示占空比百分之百 */ ENB_PWM_data = 9; /* 0表示占空比0 10表示占空比百分之百 */ while ( 1 ) { ScanKey(); /* 得到按键 */ KEY_CHULI(); /* 处理按键 */ update(); /* 更新显示 */ } } void Time0( void ) interrupt 1 { TH0 = (65536 - 1000) / 256; /* 计数初值重装载 */ TL0 = (65536 - 1000) % 256; /* 启动状态下 */ pwm_count++; if ( pwm_count == 10 ) { pwm_count = 0; if ( open == 1 ) { ENA = 0; /*传动带速度 */ } ENB = 0; /* 角度 */ } if ( ENA_PWM_data == pwm_count ) { if ( open == 1 ) { ENA = 1; /*传动带速度 */ } } if ( ENB_PWM_data == pwm_count ) { ENB = 1; /* 角度 */ } } /* 50ms */ void T1_time() interrupt 3 { unsigned int shijian = 0; TH1 = (65536 - 50000) / 256; TL1 = (65536 - 50000) % 256; num2++; if ( num2 == 20 ) { num2 = 0; /* 正计时 */ if ( time_count_mode == 0 && open == 1 ) { 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; } } } } /* 倒计时 */ if ( time_count_mode == 1 && open == 1 ) { shijian = rtc_hour * 3600 + rtc_min * 60 + rtc_sec; shijian--; if ( shijian == 0 ) { open = 0; ENA = 1; /* 关闭PWM */ } rtc_hour = shijian / 3600; rtc_min = shijian / 60 % 60; rtc_sec = shijian % 60; } } }

1602.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^4; sbit lcd_rw=P2^5; sbit lcd_en=P2^6; #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) { if (y == 0) { LCD_write_com(0x80 + x); //第一行显示 } else { LCD_write_com(0xC0 + x); //第二行显示 } while (*s) { LCD_write_data( *s); s ++; } } //*********************************************************************** // 显示屏初始化函数 //*********************************************************************** 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); }

eeprom.h

c
#include <reg52.h> #include <intrins.h> /****************特殊功能寄存器声明****************/ sfr ISP_DATA = 0xe2; sfr ISP_ADDRH = 0xe3; sfr ISP_ADDRL = 0xe4; sfr ISP_CMD = 0xe5; sfr ISP_TRIG = 0xe6; sfr ISP_CONTR = 0xe7; /* * STC89C52RC内部EEPROM详细地址表: * 第一扇区 第二扇区 第三扇区 第四扇区 * 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 * 2000h 21FFh 2200h 23FFh 2400h 25FFh 2600h 27FFH * 第五扇区 第六扇区 第七扇区 第八扇区 * 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 * 2800h 29FFh 2A00h 2BFFh 2C00h 2DFFh 2E00h 2FFFh * * * 使用举例 * cc(0X2000);//擦除第一扇区 * xcx(0x2002,2);//向地址0x2002写入2 * duqu=dcx(0x2002);//读取出来 * */ void cc( unsigned int addr ); void xcx( unsigned int addr, char dat ); char dcx( unsigned int addr ); void Q0(); /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ * 函数:擦除某一扇区(每个扇区512字节) * 入口:addr = 某一扇区首地址 * ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void cc( unsigned int addr ) { /* * 打开 IAP 功能(ISP_CONTR.7)=1:允许编程改变Flash, 设置Flash操作等待时间 * 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M) */ ISP_CONTR = 0x81; ISP_CMD = 0x03; /* 用户可以对"Data Flash/EEPROM区"进行扇区擦除 */ ISP_ADDRL = addr; /* ISP/IAP操作时的地址寄存器低八位, */ ISP_ADDRH = addr >> 8; /* ISP/IAP操作时的地址寄存器高八位。 */ EA = 0; ISP_TRIG = 0x46; /* 在ISPEN(ISP_CONTR.7)=1时,对ISP_TRIG先写入46h, */ ISP_TRIG = 0xB9; /* 再写入B9h,ISP/IAP命令才会生效。 */ _nop_(); Q0(); /* 关闭ISP/IAP */ } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ * 函数:写一字节 * 入口:addr = 扇区单元地址 , dat = 待写入数据 * ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void xcx( unsigned int addr, char dat ) { ISP_CONTR = 0x81; ISP_CMD = 0x02; /* 用户可以对"Data Flash/EEPROM区"进行字节编程 */ ISP_ADDRL = addr; ISP_ADDRH = addr >> 8; ISP_DATA = dat; /* 数据进ISP_DATA */ EA = 0; ISP_TRIG = 0x46; ISP_TRIG = 0xB9; _nop_(); Q0(); /* 关闭ISP/IAP */ } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ * 函数:读一字节 * 入口:addr = 扇区单元地址 * 出口:dat = 读出的数据 * ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ char dcx( unsigned int addr ) { char dat; ISP_CONTR = 0x81; ISP_CMD = 0x01; /* 用户可以对"Data Flash/EEPROM区"进行字节读 */ ISP_ADDRL = addr; ISP_ADDRH = addr >> 8; EA = 0; ISP_TRIG = 0x46; ISP_TRIG = 0xB9; _nop_(); dat = ISP_DATA; /* 取出数据 */ Q0(); /* 关闭ISP/IAP */ return(dat); } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ * 函数:关闭ISP/IAP操作 * ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void Q0() { ISP_CONTR = 0; /* 关闭IAP功能 */ ISP_CMD = 0; /* 待机模式,无ISP操作 */ ISP_TRIG = 0; /* 关闭IAP功能, 清与ISP有关的特殊功能寄存器 */ EA = 1; } /* 连续写入 10 字节 */ void lianxi_Write( char *pin , unsigned int addr) { char num; for ( num = 0; num < 10; num++ ) { xcx( addr + num, *pin ); /* 从0x2010开始读取32个字节 */ pin++; } } /* 连续读取 10 个字节 */ void lianxi_Read( char *pin ,unsigned int addr) { char num; for ( num = 0; num < 10; num++ ) { *pin = dcx( addr + num ) ; /* 从0x2010开始读取32个字节 */ pin++; } }
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

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