datouyuan 发表于 2021-12-13 10:21 学到了很多,谢谢大佬 |
莉雅丝 发表于 2021-12-10 17:11 串口输出字符串用sprintf函数最省事 sprintf可以自动输出负号和小数点,也可以不输出小数点,对于数据处理最省事,至少占用内存什么的,那是单片机累,我不累就行 char k[10]; //这里不能加code限定符,否则计算不正确,数组长度随意,不出错就可以 char a; sprintf(k,"%.1f",Data_Send); //把浮点数据分割成字符串,并存放在k数组中,"%.1f"的2f表示小数点后再显示1位数,不显示小数就是0f for(a=0;(k[a]!='\0');a++) { Send_Out_COM(k[a]); //发送(串口发送函数),发送的是ASCII码,避免出现0x00数据 } void Send_Out_COM(unsigned char COM) //发送一个字节数据(串口发送函数) { while(Busy); //等待上次发送完成,Busy在串口2完成发送后清除 Busy=1; S2BUF=COM; } |
莉雅丝 发表于 2021-12-10 17:11 stdio.h解决不了问题,要重定向putch才可以。 |
本帖最后由 datouyuan 于 2021-12-13 10:57 编辑 莉雅丝 发表于 2021-12-10 17:11 printf("已点亮%bd个灯\n",x);//x为8bit数 用stdio.h的printf函数是最容易做的方法。你只要完成char putchar (char c) 这个函数就行。 void send(char* c);//串口发送字符 void sends(char* str,unsigned char len);//串口发送字符串 假如不用stdio.h,你需要完成上面2个函数。 sends("已点亮",6); send(x/10+'0');send(x%10+'0');//x范围00~99 sends("个灯\n",5);//一个中文字符算2个字节,ascii算1个字节,所以长度为5 |
xianfajushi 发表于 2021-12-6 09:25 我好像找到解决方案了,好像包括一个stdio.h库文件就能用里面的函数输出字符串了,不知道有没有其他方法 |
![]() |
![]() |
定时器假如1MS? 那么是不是可以在定时中断函数里面给个标志位?比如F_1MS=1? WHILE(1){}里面我们把所有的程序都放在这个if(F_1MS){}里面可以不? 这就是前后台程序架构。 对付8位单片机足矣。 |
莉雅丝 发表于 2021-12-5 16:31 真想学很好,会有人帮助的,我也不是专门说你,只是一时感慨而已,论坛上真想学的人和只想复制粘贴的人都遇到过,前天就有人向我索要图片中的代码,我问老婆她都不同意直接给代码,不想学的人连图片拿去识别都不做, 我有代码,但回复大部分只给代码图片,为的就是不给直接复制了事,真想学的人要么就参考我的思路写法,要么就自己照着动手打代码,要么就去识别图片,不管别人如何看待我用代码图片回复,只做认为该做的,当然不包括我博客发布的代码可以复制,我学习时基本就是看别人的思路与写法,不需要复制粘贴. |
天ノ忆 发表于 2021-12-5 17:28 谢谢指导,帮助很多,刚初学没有注意这个排版,辛苦了,买的板子还没到,用仿真做的,就没写消抖了,以后一定注意排版π_π。 |
本帖最后由 188610329 于 2021-12-6 02:02 编辑 莉雅丝 发表于 2021-12-5 16:27 自己改 Mainforse 值为,你的晶振频率 #include <STC89C5xRC.H> typedef unsigned char u8; #define Mainforse 24000000L #define Timer_Base (65536 - (Mainforse / 12 / 256)) u8 T0_Count,Sec_Count,Mode,Old_Mode,New_Mode; sbit Key = P3^2; void main() { TMOD = 0x01; TL0 = Timer_Base % 256; TH0 = Timer_Base / 256; TCON = 0x11; //INT0 下降沿中断 IE = 0x83; while(1) { New_Mode = Mode; if(New_Mode != Old_Mode) { Old_Mode = New_Mode; P1 = 0xff; } if(Sec_Count > Old_Mode) { Sec_Count = Sec_Count - Old_Mode - 1; switch(Old_Mode) { case 0: P1 ^= 0x01; break; case 1: P1 ^= 0x03; break; case 2: P1 ^= 0x07; break; case 3: P1 ^= 0x0F; break; case 4: P1 ^= 0x1F; break; case 5: P1 ^= 0x3F; break; case 6: P1 ^= 0x7F; break; case 7: P1 ^= 0xFF; break; default: break; } } } } void ET0_INT(void) interrupt 0 { while(!Key); //等待按键抬起, 可以不需要 Mode++; Mode &= 0x07; // Mode 0~7 } void T0_INT(void) interrupt 1 { TL0 = Timer_Base % 256; TH0 = Timer_Base / 256; T0_Count++; if(T0_Count == 0) Sec_Count++; } |
188610329 发表于 2021-12-5 16:35 不太懂中断这一块,我能用定时器0写一个延时函数,然后在case里调用吗 |
你这程序按键那个地方就不对,你随便找本书,关于按键地方肯定会写消抖,你这程序里并没有消抖,这会导致数据出错,当然也不是一定会出错,只是出错的几率大大增加。 定时器设置直接抄书就可以,但是最好是自己理解清楚。 延时函数可以去烧录那个软件生成一个。 switch()里面为什么要这么写,先说P1 = 0xFE;之后紧跟一句P1 = 0XFF;你这个写法意思是人眼视觉停留时间比单片机运行一条指令的时间还短吗,你中间不加个延时怎么用眼睛看到IO口变化, 其次,你这for循环也起不到改变间隔的作用,因为你if成立之后程序还要跑完剩下的for,加起来间隔是一样的, 如果按你这个想法倒不如这样写
好像这样不知不觉就写完了,最后,最重要的一点就是,你代码的排版简直烂透了,不要为了图省事就随便写,代码排版好看点对人对己都有好处 |
本帖最后由 188610329 于 2021-12-5 20:30 编辑 莉雅丝 发表于 2021-12-5 16:27 代码如下,你要觉得能用就用,不能用就算了。 #include <STC89C5xRC.H> typedef unsigned char u8; #define Mainforse 24000000L #define Timer_Base (65536 - (Mainforse / 12 / 256)) u8 T0_Count,Sec_Count,Mode,Old_Mode,New_Mode; sbit Key = P3^2; void main() { TMOD = 0x01; TL0 = Timer_Base % 256; TH0 = Timer_Base / 256; TCON = 0x11; //启动TR0, INT0 下降沿中断 IE = 0x83; //EA = 1, EX0 =1 , ET0 = 1 while(1) { New_Mode = Mode; if(New_Mode != Old_Mode) { Old_Mode = New_Mode; P1 = 0xff; } if(Sec_Count > Old_Mode) { Sec_Count = Sec_Count - Old_Mode - 1; switch(Old_Mode) { case 0: P1 ^= 0x01; break; case 1: P1 ^= 0x03; break; case 2: P1 ^= 0x07; break; case 3: P1 ^= 0x0F; break; case 4: P1 ^= 0x1F; break; case 5: P1 ^= 0x3F; break; case 6: P1 ^= 0x7F; break; case 7: P1 ^= 0xFF; break; default: break; } } } } void INT0(void) interrupt 0 { while(!Key); //等待按键抬起, 如IT0 = 1, 可以不需要 Mode++; Mode &= 0x07; // Mode 0~7 } void T0_INT(void) interrupt 1 { TL0 = Timer_Base % 256; TH0 = Timer_Base / 256; T0_Count++; if(T0_Count == 0) Sec_Count++; } |
莉雅丝 发表于 2021-12-5 16:18 如果,你用delay 延时来让灯闪烁,你的按键,就必须用 中断来检测, 如果按键不想用 中断,那么闪烁就必须用 定时器中断来控时,总之, 要达到你的最终目的, 必须要有 1个以上的中断。 |
xianfajushi 发表于 2021-12-5 08:09 我其实没有想复制粘贴,交这个作业还要讲解思路,而且我也是真心想学单片机 |
liuzx66 发表于 2021-12-5 13:15 这跟我思路不一样,我试试,感谢思路 |
188610329 发表于 2021-12-4 22:09 第一次提问,没想到这个问题 |
1、定时器定时1ms中断,中断程序里面用一个变量来记录中断次数。变量类型要能存储足够大的数据,能够满足你的要求。 2、主程序判断这个变量,到1S(1000ms)做什么,到2S做什么......以此类推。 3、到最后把变量清零,重新开始。如果不清零变量就要特殊处理一下也可以。 |
首先你需要知道什么功能要放在while循环中让他不断重复,很明显你这个按键检测是必需的,灯的闪烁是根据按键的值被选择的,至于定时器只起到了一个调整间隔的作用,你可以先写按键检测,在这个基础上加入灯,每个模式封装成一个函数,按键扫描的值存到一个变量中,根据这个变量来调用不同的模式,在不同模式下调整计时器 |
本帖最后由 xianfajushi 于 2021-12-5 11:08 编辑
|
现在网络提供的代码较多了,可能是为了防止新生不学无术,题目都稍有改动新生就不能即刻复制粘贴了事,老师也是被逼无奈,为了新生的苦心!所以我现在看到稍有不同的题目直接不去回复,新生应该通过理解稍加修改即可。本题随意设定定时器时间都只是基本的数学计算问题。比如定时50毫秒乘10就是半秒闪烁就是一秒,之后10乘以2就是2秒闪烁,如此类推,按键也是很简单的控制一个量值即可实现循环控制。 |
你多多少少写点出来,那么人家根据你的代码,评估一下你的水平,适当的帮你改一改,也不是不可能。 你现在是出题? 然后,人家答题? 人家随便扔个代码上来,你确定你就能用了么?确定能看懂么? |