单片机C语言的程序问题
这个程序怎么看?(我在后面加//的希望您能帮我重点解释下)
#include <REG52.H> #include <INTRINS.H> sbit Beep = P1^5 ; unsigned char n=0; unsigned char code music_tab[] ={乐谱省略 }; void int0() interrupt 1 //这个函数实现什么功能,是怎么实现的? { TH0=0xd8; TL0=0xef; n--; } void delay (unsigned char m) { unsigned i=3*m; while(--i); } void delayms(unsigned char a) { while(--a); //为什么不采用while(a--); } void main() //能按照程序运行过程将主函数逐条解释下 { unsigned char p,m; unsigned char i=0; TMOD&=0x0f; TMOD|=0x01; TH0=0xd8;TL0=0xef; IE=0x82; play: while(1) { a: p=music_tab[i]; if(p==0x00) { i=0, delayms(1000); goto play;} else if(p==0xff) { i=i+1;delayms(100),TR0=0; goto a;} else {m=music_tab[i++], n=music_tab[i++];} TR0=1; while(n!=0) Beep=~Beep,delay(m); TR0=0; } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
谢谢您的鼓励。
楼主,整体我只能给个大概。没有明确的整体系统设计资料,我无法给出准确的说明。
可能有人说,我一眼就能看出是什么单片机,所以对应的什么就一定是什么。那这个是没被C的宏害过的。
你要想彻底搞清楚,实际上整个环境你要摸清楚。例如对引脚的设置,对地址的设置,对CPU模式的设置,这些都是比较细的工作。但如果你想搞透,还是要仔细看的。这我帮不了你。没时间,没资料。就是什么都有了。我给你解释完整了。对你反而也没什么帮助了。
但特别是单片机这种东西,你这样细枝末节的追求是对的,更多要自己去摸。这对理解计算机组成原理和CPU运行原理很有帮助。以后碰到复杂的CPU就不怕了。最好是自己动手去堆个板子。
回复
TMOD之类的,我得看到资料和定义才能明确说是什么。TRO=1,TRO=0,不存在执行,是对寄存器或指定地址直接设置值的工作。也可能属于一个中断响应设置,启动后调用int0。Beep =~Beep后面用,号,这我还真不知道,以目前的信息。n是在中断响应程序int0中进行了改变。
回复
单片机编程都和你实验用的硬件紧密关系的。怎么接线,什么硬件,都有它对应的API和使用方法。我觉得你最应该看的是运行这个程序的单片机的线路图和上面接的芯片的文档。只要搞清楚那个,这个程序是干什么的就一目了然了。
回复
谢谢,您刚才这样一点拨,我应该差不多看懂了,我再仔细看看,将细节在搞搞清楚,谢谢您。
回复
成败在细节。扣细节的人,会成功的。哈。不用怕,注意要多对整个开发对象的整体环境的理解。我写一个XDMA驱动,也是折腾了2个星期,就是反复测试,反复看资料才摸出来的。都一样。不要以为老人折腾这些就容易,特别是新鲜玩意。
回复
谢谢您的指教。
哈。冲你提 while(--a); //为什么不采用while(a--);这个问题,
我觉得还是值得说两句的。
跟着 @Lunar_Lin 的解释之后。我说下main 的执行。
前面一块是配置,应该是宏,我不清楚你用的是什么单片机以及宏怎么定义的,但通常这些宏对应的是单片机外部引脚。为什么是某个值,这个要看电路。为什么是位操作很多,因为一个位对应一个引脚。
play: 这个没什么东西,就是一个label
while(1)是个死循环。正常的代码都这样。包括很多GUI的代码,例如在WIN下面开发的窗口程序。一般学校学习的人,或者应用开发的人,很少碰到程序中间这个while (1)。你可以想象,没有这个while (1)的代码,通常是呼一下就跑完退出的代码。
而while (1)的死循环是为了让程序保持。保持中,通过状态的调整来完成程序的退出或其他功能的实现。
这里说一句,play: a: 这两个label 没有意义,goto的地方可以用continue。我不知道这个代码是依葫芦画瓢抄出来的,还是删了代码。
music_tab算是个数组,如果0,和0xff怎进行简单的响或不响处理。其他情况则做了个数值到对外实际输出的转换。你可以看做是种驱动代码。这里使用了16bits。n,m都使用了8位。
谢谢,您刚才的解释对我很有帮助。 我是个初学者,我想问的还有主函数是怎么执行的,能一条一条解释吗?
回复
这个不现实..... 你得自己慢慢弄.
回复
还是很谢谢你的帮助。
void int0() interrupt 1
是中断向量函数. 指示编译链接器将该函数的代码放在中断向量1的位置, 发生中断号为1的中断时候, CPU将执行该函数.
while(--a); //为什么不采用while(a--);
CC++ 后缀增减表达式会产生临时变量, 你可以搜索 "前缀 自增 后缀 临时对象 C++" . 不过在这里应该是毫无意义的. 该函数只是用来延时, 节省CPU是没意义的事情. delayms这个函数名字也是有问题的. 如果是这个名字,至少实现上 要有cpu执行指令的周期数, 该款cpu的晶振数. (或许是因为是因为CPU恰好1ms 执行 --a,判断语句 2个指令 ?? 这cpu也太慢了......) 呵呵 你可以搜索下 单片机上延时函数的正统做法.