完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛
|
看到鸿哥的回帖,万分感动,浑身力量啊,学习更有劲了,更加努力地上班。 其实很久以前就想加鸿哥的qq,但是没加,一直在论坛交流,就怕打扰到鸿哥的工作。 |
|
|
|
|
|
|
|
|
开场白: 直接用C语言的“-”运算符进行减法运算时,“被减数”,“减数”,“差”,这三个数据的最大范围是unsigned long 类型,也就是数据最大范围是4个字节,十进制的范围是0至4294967295。一旦超过了这个范围,则运算会出错。因此,当进行大数据减法运算时,我们要编写专用的减法程序,这种算法就是我们在小学里学的四则运算。 我们先要弄清楚一个新的概念。一个数据在不考虑小数点的情况下,有两种表现形式。一种是变量形式,一种是数组 形式。这两种数据的表现形式可以通过一个函数相互转换。比如一个系统里数据的最大有效位数是36位。如果用变量形式,因为一个unsigned long变量最多只能容纳9位十进制的有效数据,因此我们就需要4个unsigned long变量。如果用数组形式,我们就需要一个能容纳36个unsigned char数据的数组。比如: (a) 用变量形式表示 4212345678这个数据。 unsigned long opera_left_var[4]; //定义4个变量。 opera_left_ var [0]= 212345678; //第1至第9位有效数据 opera_left_ var [1]= 4; //第10至第18位有效数据 opera_left_ var [2]= 0; //第19至第27位有效数据 opera_left_ var [3]= 0; //第28至第36位有效数据 (b) 用数组形式表示 4212345678这个数据。 unsigned char opera_left_array[36]={ //定义一个可以容纳36个数据的数组 8,7,6,5,4,3,2,1,2, //第1至第9位有效数据 4,0,0,0,0,0,0,0,0, //第10至第18位有效数据 0,0,0,0,0,0,0,0,0, //第19至第27位有效数据 0,0,0,0,0,0,0,0,0, //第28至第36位有效数据 }; 因为核心算法部分都是以数组形式进行,因此运算前必须先把变量数据转换成数组数据,运算结束后再把数组数据转换成变量数据。也就是先“化整为零”,最后再“化零为整”。 本算法不考虑运算结果为负数的情况,也就是“被减数”必须不能小于“减数”。如果读者遇到要考虑负数的项目,运算之前只需要判断一下“被减数”和“减数”谁大谁小,一旦发现“减数”大于“被减数”,那么就把“减数”和“被减数”相互对调一下,然后记上运算结果的符号是负数就可以了。 (1)功能需求: 按一个按键,如果4287654321-4212345678的运算结果是75308643,则蜂鸣器长鸣一声表示运算正确。否则,短鸣一声表示运算错误。 (2)硬件原理: 独立按键的电路请参考第二节。 (3)源码适合的单片机: PIC18f4520,晶振为3.579545MHz。 |
|
|
|
|
|
|
|
|
我会告诉你我在学校只学过半年的单片机现在从事的就是单片机工作么。。。孩子,重点不是还有没有救,重点是大四的时候找个好工作。。。祝你好运。。。 |
|
|
|
|
|
|
|
|
我当时是碰到一个项目要用到CPLD,所以就买了一块学习板和几本书来学。 |
|
|
|
|
|
|
|
|
本帖最后由 552152750 于 2013-7-28 11:19 编辑
大师。。。。我想问下大师对舞台灯光的程序又没用研究,因为我在一家舞台灯光厂做技术员,他的程序都是通用程序,就是工厂没有程序,要写程序的话就要找那些有程序的人来写,而且这些写程序的人可以给很多的灯光厂写程序,我现在跟着吴大师学习了也好长时间,也希望找个项目来深入学习,他的平台高级就要ARM的,低档的就是STC,很想听下大师的见解。看大师的回帖有时候感觉很开心很轻松,很想学习,千言万语心情复杂,愿吴大师心情好,工作好,钱也好。。。。。。
|
|
|
|
|
|
|
|
|
#include
//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr #define beep_dr LATA1 //蜂鸣器输出 #define key_dr1 LATB3 //2X2按键行输出 #define key_dr2 LATB4 //2X2按键行输出 #define key_sr1 RB6 //2X2按键行输入 #define key_sr2 RB7 //2X2按键行输入 //补充说明:吴坚鸿程序风格是这样的,凡是做延时计数阀值的常量 //前缀都用cnt_表示。 #define cnt_delay_cnt1 25 //按键去抖动延时阀值 #define cnt_delay_cnt2 5 //按键行输出信号稳定的小延时阀值 #define cnt_voice_time 60 //蜂鸣器响的声音长短的延时阀值 void delay1(unsigned int de) ;//小延时程序,时间不宜太长,因为内部没有喂看门狗 //补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中 //断里,凡是按键服务程序都是放在main函数循环里。有人说不应该把子程序//放在中断里,别听他们,信鸿哥无坎坷。 void key_scan(); //按键扫描函数,放在定时中断里 void key_service(); //按键服务函数,放在main函数循环里 //补充说明:吴坚鸿程序风格是这样的,凡是switch()语句括号里面的变量名 //后缀都用_step表示。 unsigned char key_step=1; //按键扫描步骤变量,在switch()语句的括号里 //补充说明:吴坚鸿程序风格是这样的,凡是按键或者感应输入的自锁变量名 //后缀都用_lock表示。 unsigned char key_lock1=0; //按键自锁标志 //补充说明:吴坚鸿程序风格是这样的,凡是计数器延时的变量 //后缀都用_cnt表示。 unsigned int delay_cnt1=0; //延时计数器的变量 unsigned int delay_cnt2=0; //延时计数器的变量 unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时 //补充说明:吴坚鸿程序风格是这样的,凡是做类型的变量的分类 //后缀都用_sec表示。 Unsigned char key_sec=0; //哪个按键被触发 //主程序 main() { ADCON0=0x00; ADCON1=0x0f; //全部为数字信号 ADCON2=0xa1; //右对齐 RBPU=0; //上拉电阻 SSPEN=0; //决定RA5不作为串口 TRISB3=0; //配置按键行扫描IO为输出 TRISB4=0; //配置按键行扫描IO为输出 TRISB6=1; //配置按键列扫描IO为输入 TRISB7=1; //配置按键列扫描IO为输入 T1CON=0x24; //定时器中断配置 TMR1H=0xF5; TMR1L=0x5F; TMR1IF=0; TMR1IE=1; TMR1ON=1; TMR1IE=1; //补充说明,以上的内容为寄存器配置,每种不同的单片机会有点差异, //大家不用过度关注以上寄存器的配置,只要知道有这么一回事即可 beep_dr=0; //关蜂鸣器,上电初始化IO while(1) { CLRWDT(); //喂看门狗,大家不用过度关注此行 key_service(); //按键服务 } } void key_scan() //按键扫描函数 { //补充说明:如果中断一次就把所有的按键都扫描完,中断占用的时间片就会太多,势//必会影响main函数里其他子程序的运行,为了避免一口气把所//的按键都扫描完,此 //处用switch语句把4个按键分成2等分,一次中断只扫描2个按键 switch(key_step) //按键扫描步骤, { case 1: //扫描1号键,2号键 key_dr1=0; //按键行扫描输出第一行低电平 key_dr2=1; delay_cnt2=0; //延时计数器清零 key_step++; //切换到下一个运行步骤 break; case 2: delay_cnt2++; if(delay_cnt2>cnt_delay_cnt2) //小延时,但不是去抖动延时,替代一直受网友争议的delay1(40) { delay_cnt2=0; key_step++; //切换到下一个运行步骤 } break; case 3: if(key_sr1==1&&key_sr2==1) { //如果没有按键按下,则2个IO输入都是高电平 key_step++; //如果没有按键按下,下一个中断扫描下2个 //按键 key_lock1=0; //按键自锁标志清零 delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙 } Else if(key_sr1==0&&key_sr2==1&&key_lock1==0) { // key_lock1按键自锁,避免按键一直触发,下降沿有效 ++delay_cnt1; //延时计数器 //补充说明:有按键触发之后,不要马上响应,要延时一段时间去抖动,此处本人设计非常 //巧妙,很多人仅仅知道按键延时的时候要保证还能去处理别的程序,这样是还不够的, //在延时去抖动的时候,还必须要监控延时这段时间里,按键IO输入口是否会由于受到某//种干扰突然由低变成高,如果一旦变成高,那么延时计数器delay_cnt1必须重新清零 //我当年就是因为这样处理,把卖给富士康100台受干扰死机的设备修好了,老板马上 //给我加薪1000元。 if(delay_cnt1>cnt_delay_cnt1) //延时计数器超过一定的数值 { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发,只有松开按键, //此标志位才会被清零 key_sec=1; //触发1号键 } } else if(key_sr1==1&&key_sr2==0&&key_lock1==0) { ++delay_cnt1; if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 key_sec=2; //触发2号键 } } break; case 4: //扫描//扫描3号键,4号键 key_dr1=1; key_dr2=0; //按键行扫描输出第二行低电平 delay_cnt2=0; //延时计数器清零 key_step++; //切换到下一个运行步骤 break; case 5: delay_cnt2++; if(delay_cnt2>cnt_delay_cnt2) //小延时,但不是去抖动延时,替代一直受网友争议的delay1(40) { delay_cnt2=0; key_step++; //切换到下一个运行步骤 } break; case 6: if(key_sr1==1&&key_sr2==1) { key_step++; key_lock1=0; delay_cnt1=0; } Else if(key_sr1==0&&key_sr2==1&&key_lock1==0) { ++delay_cnt1; if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; key_sec=3; //触发3号键 } } else if(key_sr1==1&&key_sr2==0&&key_lock1==0) { ++delay_cnt1; if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 key_sec=4; //触发4号键 } } break; } if(key_step>6) //第1组按键与第2组按键反复轮流扫描 { key_step=1; } } void key_service() //按键服务函数 { switch(key_sec) //按键服务状态切换 { case 1:// 1号键 // 补充说明:voice_time_cnt只要不为0蜂鸣器就会响,中断里判断voice_time_cnt不为0 //时,会不断自减,一直到它为0时,自动把蜂鸣器关闭 voice_time_cnt= cnt_voice_time; //蜂鸣器响“滴”一声就停 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零, //避免一直触发 break; case 2:// 2号键 voice_time_cnt= cnt_voice_time; //蜂鸣器响“滴”一声就停 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零, //避免一直触发 break; case 3://3号键 voice_time_cnt= cnt_voice_time; //蜂鸣器响“滴”一声就停 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零, //避免一直触发 break; case 4://4号键 voice_time_cnt= cnt_voice_time; //蜂鸣器响“滴”一声就停 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零, //避免一直触发 break; } } //中断 void interrupt timer1rbint(void) { if(TMR1IE==1&&TMR1IF==1) //定时中断 { TMR1IF=0; //定时中断标志位关闭 TMR1ON=0; //定时中断开关关闭 key_scan(); //按键扫描函数 if(voice_time_cnt) //控制蜂鸣器声音的长短 { beep_dr=1; //蜂鸣器响 |
|
|
|
|
|
|
|
|
我也不是万能的,没弄过舞台灯光的。虽然我号称走大师路线,其实本质上我还是屌丝。 只要会了编程的框架,任何程序的逻辑都是相同的,这样吧,等我把算术篇写完了, 我接着专门写几节关于单片机中的战斗机---switch语句的用法。再复杂的逻辑程序都可以用switch来编写。 |
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2382 浏览 1 评论
4242 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2619 浏览 2 评论
3118 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4577 浏览 5 评论
有套STM32与西门子200程序需要代写,有兴趣的工程师与有联系!
2491浏览 1评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6801浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-18 03:54 , Processed in 1.001073 second(s), Total 83, Slave 74 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖