完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛
|
鸿哥,你左边资料里的qq交谈啊,短信啊什么的是怎么设置的?我的啥也没有。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-8-18 09:10 编辑
第四十五节:算术篇---大数据的除法运算 开场白: 直接用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)功能需求: 按一个按键,如果123456789123456789 / 987654321的运算结果是124999998,则蜂鸣器长鸣一声表示运算正确。否则,短鸣一声表示运算错误。 (2)硬件原理: 独立按键的电路请参考第二节。 (3)源码适合的单片机: PIC24fj128ga006,晶振为11.0592MHz。 (4)单片机的C语言源代码讲解:请下载本节的附件。 (5)下集预告: 单片机中的战斗机switch---利用主函数循环实现LED灯闪烁。 (未完待续,下节更精彩,不要走开哦!)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
刚看到这个帖子,hong ge V5!学习了
|
|
|
|
|
|
|
|
|
鸿哥,你的却是大神,看你的代码风格就知道了,膜拜
|
|
|
|
|
|
|
|
|
支持,感谢楼主分享
|
|
|
|
|
|
|
|
|
呵呵,把您拍在沙滩上早着呢! 做PCB板,C++编写上位机软件,CPLD或FPGA, 都要学啊。今年刚工作,就奔着您这条线走了。 |
|
|
|
|
|
|
|
|
不懂:画矩形处第二个”//复制改动处“下的”write_data(0x01)“,点解不是”0x80“?(是因为矩形的”x长度“的单位是”字节“?)
|
|
|
|
|
|
|
|
|
第四节51移植 手头上没有74HC165芯片所以未上机实验
/*第四节:“鸿哥三宝”之74HC165(按键扫描篇) (1) 开场白: 这节将要跟大家介绍一下鸿哥的“三宝”,它们分别是74HC165,74HC595,ULN2003A.之所以它们在我心中的地位那么高,是因为很多工控小项目经常用到它。74HC165使我们从此不再为单片机的输入口不足而烦恼,我们用3根IO口就可以检测100多路的输入信号。74HC595使我们从此不再为单片机的输出口不足而烦恼,我们用4根IO口就可以驱动100多个继电器或者LED。而ULN2003A则大大简化了我们的三极管驱动电路,一个芯片就集成了7个三极管,它有500mA的驱动能力,内部自带续流二极管,用来驱动继电器的时候,二极管也省了。74HC165对静电很敏感,很脆弱,在通电的情况,绝对不要用手摸到他的引脚,我曾经用非绝缘的镊子来短接其输入口,烧坏了很多个,因此对于74HC165我们要懂得怜香惜玉,小心呵护。总之,“鸿哥三宝”实乃电子工程师居家旅行之必备良药。 (2)功能需求:每按一个按键,蜂鸣器就响一次。 (3)硬件原理: (a)把两个74HC165联级起来,就可以达到用3根IO口来检测16个按键的目的。此电路的本质是并入串出的原理。具体的电路读者只要下载芯片资料一看就明。还是那句话,按键那里记得接20K左右的上拉电阻。 (b)用1个IO经过8050三极管来驱动有源蜂鸣器,有源蜂鸣器通电就一直响,断电就停止。 (4)源码适合的单片机:STC98C52RC,晶振为12MHz (5)源代码讲解如下:*/ #include #include //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr ***it beep_dr = P1^0; //蜂鸣器输出 ***it hc165_cp_dr = P1^1; //74hc165的3根驱动IO之一 时钟 ***it hc165_pl_dr = P2^2; //74hc165的3根驱动IO之一 芯片控制 ***it hc165_q7_sr = P2^3; //74hc165的3根驱动IO之一 芯片的输出 //补充说明:吴坚鸿程序风格是这样的,凡是做延时计数阀值的常量 //前缀都用cnt_表示。 #define cnt_delay_cnt1 40 //按键去抖动延时阀值 #define cnt_voice_time 150 //蜂鸣器响的声音长短的延时阀值 //补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中 //断里,凡是按键服务程序都是放在main函数循环里。有人说不应该把子程序//放在中断里,别听他们,信鸿哥无坎坷。 void key_scan(); //按键扫描函数,放在定时中断里 void key_service(); //按键服务函数,放在main函数循环里 //补充说明:吴坚鸿程序风格是这样的,凡是switch()语句括号里面的变量名 //后缀都用_step表示。 unsigned char key_step=1; //按键扫描步骤变量,在switch()语句的括号里 //补充说明:吴坚鸿程序风格是这样的,凡是按键或者感应输入的自锁变量名 //后缀都用_lock表示。 unsigned char key_lock1=0; //按键自锁标志 unsigned char key_lock2=0; //按键自锁标志 unsigned char key_lock3=0; //按键自锁标志 unsigned char key_lock4=0; //按键自锁标志 //补充说明:吴坚鸿程序风格是这样的,凡是计数器延时的变量 //后缀都用_cnt表示。 unsigned int delay_cnt1=0; //延时计数器的变量 unsigned int delay_cnt2=0; //延时计数器的变量 unsigned int delay_cnt3=0; //延时计数器的变量 unsigned int delay_cnt4=0; //延时计数器的变量 unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时 //补充说明:吴坚鸿程序风格是这样的,凡是做类型的变量的分类 //后缀都用_sec表示。 unsigned char key_sec=0; //哪个按键被触发 unsigned int key_status=0; //一个字节8位,此处2个字节,共16位,每一位代表一////个按键的状态 //主程序 main() { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 TH0=0x1c; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 TL0=0x18; EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 //补充说明,以上的内容为寄存器配置,每种不同的单片机会有点差异, //大家不用过度关注以上寄存器的配置,只要知道有这么一回事即可 beep_dr=0; //关蜂鸣器,上电初始化IO while(1) { //CLRWDT(); //喂看门狗,大家不用过度关注此行 key_service(); //按键服务 } } void key_scan() //按键扫描函数 { unsigned char j; //中间循环变量 key_status =0x0000; //每个按键的电平状态,共16个 hc165_pl_dr=0; //装载 _nop_(); _nop_(); _nop_(); hc165_pl_dr=1; //移位 _nop_(); _nop_(); _nop_(); for(j=0;j<16;j++) { hc165_cp_dr=0; //时钟低电平 _nop_(); _nop_(); _nop_(); key_status=key_status<<1; if(hc165_q7_sr==1)key_status=key_status+1; hc165_cp_dr=1; //时钟高电平 _nop_(); _nop_(); _nop_(); } //以上一小段代码是通过驱动2个74HC165来获取16个按键的电平状态key_status //以下代码通过解析每一位电平状态来确定哪个按键被触发 if((key_status &0x0001)==0x0001) { key_lock1=0; //按键自锁标志清零 delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock1==0) { ++ delay_cnt1; if(delay_cnt1> cnt_delay_cnt1) //延时计数去抖动 { delay_cnt1=0; key_lock1=1; key_sec=1; //触发1号键 } } if((key_status &0x0002)==0x0002) { key_lock2=0; //按键自锁标志清零 delay_cnt2=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock2==0) { ++ delay_cnt2; if(delay_cnt2> cnt_delay_cnt1) //延时计数去抖动 { delay_cnt2=0; key_lock2=1; key_sec=2; //触发2号键 } } if((key_status &0x0004)==0x0004) { key_lock3=0; //按键自锁标志清零 delay_cnt3=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock3==0) { ++ delay_cnt3; if(delay_cnt3> cnt_delay_cnt1) //延时计数去抖动 { delay_cnt3=0; key_lock3=1; key_sec=3; //触发3号键 } } if((key_status &0x0008)==0x0008) { key_lock4=0; //按键自锁标志清零 delay_cnt4=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock4==0) { ++ delay_cnt4; if(delay_cnt4> cnt_delay_cnt1) //延时计数去抖动 { delay_cnt4=0; key_lock4=1; key_sec=4; //触发4号键 } } //如果要接16个按键,读者可以继续往下添加类似的代码,本例只触发4个按键作为演示 } 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 Timer0_isr(void) interrupt 1 using 1 { TR0=0; //定时中断开关关闭 key_scan(); //按键扫描函数 if(voice_time_cnt) //控制蜂鸣器声音的长短 { beep_dr=1; //蜂鸣器响 --voice_time_cnt; //蜂鸣器响的声音长短的计数延时 } else { beep_dr=0; //蜂鸣器停止 } TH0=0x1c; //重新设置定时时间间隔 TL0=0x18; TR0=1; //定时中断开关打开 } |
|
|
|
|
|
|
|
|
这类问题太细太深了,我也不知道该怎么回答,因为我也忘得一干二净。想知道答案,你只有亲自搭电路验证一下,才知道是不是我写错了。 |
|
|
|
|
|
|
|
|
继续努力,加油。 |
|
|
|
|
|
|
|
|
本帖最后由 friend0720 于 2016-2-25 18:03 编辑
!!!!!!!!!!!!!!!!! |
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是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 02:16 , Processed in 1.014272 second(s), Total 86, Slave 77 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖