完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
|
|
165内部寄存器的移位是CP的上升沿触发的,感觉165的读操作放在CP上升沿动作完成后,不知道对不对 如下代码 hc165_cp_dr=0; asm("nop"); asm("nop"); key_status=key_status<<1; if(hc165_q7_sr==1)key_status=key_status+1; hc165_cp_dr=1; asm("nop"); asm("nop"); 改为如下 hc165_cp_dr=0; asm("nop"); asm("nop"); hc165_cp_dr=1; key_status=key_status<<1; if(hc165_q7_sr==1)key_status=key_status+1; asm("nop"); asm("nop"); |
|
|
|
|
|
好,学习了
|
|
|
|
|
|
牛人{:20:}
|
|
|
|
|
|
{:1:}
|
|
|
|
|
|
//用 switch 命令(有意不放在中断程序中)实验程序// //用STC89C52RC来做每秒点亮一只LED的实验,外晶振12MHZ, 1ms中断一次 // //实验中出现的无法理解的问题:(任务2的语句与任务1的无区别,但执行的效果却不同) // case 1:{ if(t==0) Y1=0; if(a==2)Y1=1; } break; //a为1-2秒之间(含1秒,不含2秒)时要执行的任务 // 先点亮LED1,如果a的值是2就灭了LED1, // 按理执行任务1时a的值应该不会是2的,是不会执行Y1=1的, // 但实际为何会执行Y1=1,输出高电平,让LED1亮一秒就灭了,达不到 “未到8秒时保持亮着"的要求// // case 2:{if(t==0)Y2=0;if(a==3)Y2=1; }break; //a为2-3秒之间(含2秒,不含3秒)时要执行的任务 // 任务2的语句与任务1的无区别,实际却能达到 LED2“未到8秒时保持亮着"的要求// // 实验程序如下// #include #include #define uint unsigned int //定义变量类型 0----65535// uint t; //时间(毫秒)的变量(t在0-1000之间变化,t满1000向a进一,并本身清0)// #define uchar unsigned int//定义变量类型 0-255 // uchar a; //按时序(秒)不同来分配任务的变量( a在0-11之间轮回变化)// ***it Y0=P2^1; // 定义8只LED(LED0--LED7)的驱动脚 ***it Y1=P2^2; // 5V通过一只1K电阻与一只LED串联到相应的驱动脚 ***it Y2=P2^3; // 一共要用8只1K电阻与8只LED ***it Y3=P2^7; // 驱动脚为低电平时相应的LED就亮 ***it Y4=P2^6; // 驱动脚为高电平时相应的LED就灭 ***it Y5=P2^5; // ***it Y6=P2^4; // ***it Y7=P2^0; // void main( ) //主程序// { TMOD=0x01; // 设置定时器0为工作方式1// TH0=(65536-1000)/256; //高8位装数=商// TL0=(65536-1000)%256; //低8位装数=余数// EA=1; //开总中断 ET0=1; //开定时器0中断 TR0=1;//启动定时器0 while(1) //程序来到这里就永不回头去执行上面的6个语句,如果未到中断时刻,就不会进入中断程序里,只是不断扫描下面的语句// { switch(a) //按不同时刻a的值不同去执行0-7秒间的任务 { case 0: Y0=0; break; //a为0-1秒之间(不含1秒)时要执行的任务 LED0亮(未到8秒时保持亮着) case 1:{ if(t==0) Y1=0; if(a==2)Y1=1; } break; //a为1-2秒之间(含1秒,不含2秒)时要执行的任务 // 先点亮LED1,如果a的值是2就灭了LED1 //按理执行任务1时a的值应该不会是2的,是不会执行Y1=1的, //但实际为何会执行Y1=1,输出高电平,让ED1亮一秒就灭了,达不到 “未到8秒时保持亮着"的要求// case 2:{if(t==0)Y2=0;if(a==3)Y2=1; }break; //a为2-3秒之间(含2秒,不含3秒)时要执行的任务 //任务2的语句与任务1的无区别,实际却能达到 LED2“未到8秒时保持亮着"的要求// case 3:Y3=0; break; //a为3-4秒之间(含3秒,不含4秒)时要执行的任务 LED3亮(未到8秒时保持亮着) case 4:Y4=0; break; //a为4-5秒之间(含4秒,不含5秒)时要执行的任务 LED4亮(未到8秒时保持亮着) case 5:Y5=0; break;// a为5-6秒之间(含5秒,不含6秒)时要执行的任务 LED5亮(未到8秒时保持亮着) case 6:Y6=0; break; //a为6-7秒之间(含6秒,不含7秒)时要执行的任务 LED6亮(未到8秒时保持亮着) case 7:Y7=0; break; // a为7-8秒之间(含7秒,不含8秒)时要执行的任务 LED7亮(未到8秒时保持亮着) } if(a==8) P2=0xff; // a为8-9秒之间(含8秒,不含9秒)时要执行的任务 8只LED全灭 if(a==9) P2=0; // a为9-10秒之间(含9秒,不含10秒)时要执行的任务 8只LED全亮 if(a==10) P2=0xff; // a为10-11秒之间(含10秒,不含11秒)时要执行的任务 8只LED全灭 } } void exter0() interrupt 1 //定时器0的中断程序// { TH0=(65536-1000)/256; //重装数 TL0=(65536-1000)%256; t++; //让定时器0每溢出1次t就自加一,进行累积// if(t==1000){a++;t=0;} //1秒到,a就自加一,并让t清0,好让按时刻的不同去执行相应的任务// if(a==11){a=0;} //到第11秒时a清0,让a在0-11之间轮回,程序就会重复执行相应的任务// } |
|
|
|
|
|
|
|
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-3-30 18:04 编辑
第二十二节:利用74HC595辅助来动态扫描数码管 (1) 开场白: 这种数码管驱动方式跟上一节的纯IO口动态扫描数码管的原理是一摸一样的,性能也差不多。唯一的区别是:在需要驱动很多数码管的时候,利用74hc595辅助可以节省单片机的IO口。74hc595仅仅是用来驱动数码管的COM口,数码管的SEG口还是直接用单片机的8根IO口来驱动。比如同样是要驱动显示16个数码管,用纯IO口的方式就需要占用24根IO口(8+16=24),而利用74hc595只需要11根IO口(8+3),因为单片机驱动2片联级的74hc595只需要3根IO口。大家现在应该知道为什么我要在第五节里授予74hc595”鸿哥三宝”的荣誉称号了吧?因为它太给力了。 (2) 功能需求: 在16个数码管中,从左到右,依次显示“1234567887654321”。 (3)硬件原理: 用8根单片机IO口经过中间串接470欧电阻连接到数码管的seg引脚,另外用3根IO口直接驱动2片联级74hc595芯片,2片联级74hc595芯片一共有16路输出IO口,分别经过3片ULN2003A之后直接驱动16个数码管的com引脚。ULN2003A也是“鸿哥三宝”之一,它内部集成了7路三极管,每路三极管可以驱动500mA以下的电流。本程序是驱动16位的共阴数码管。 (4)源码适合的单片机: PIC18f4520,晶振为11.0592MHz。 (5)源代码讲解如下: #include //74HC595的OE引脚直接硬件接地 # define hc595_sh_dr LATA3 //74hc595的3根驱动IO之一 # define hc595_st_dr LATA4 //74hc595的3根驱动IO之一 # define hc595_ds_dr LATA5 //74hc595的3根驱动IO之一 #define const_left_com1 0x0001 //左边第1个数码管的com显示 #define const_left_com2 0x0002 //左边第2个数码管的com显示 #define const_left_com3 0x0004 //左边第3个数码管的com显示 #define const_left_com4 0x0008 //左边第4个数码管的com显示 #define const_left_com5 0x0010 //左边第5个数码管的com显示 #define const_left_com6 0x0020 //左边第6个数码管的com显示 #define const_left_com7 0x0040 //左边第7个数码管的com显示 #define const_left_com8 0x0080 //左边第8个数码管的com显示 #define const_left_com9 0x0100 //左边第9个数码管的com显示 #define const_left_com10 0x0200 //左边第10个数码管的com显示 #define const_left_com11 0x0400 //左边第11个数码管的com显示 #define const_left_com12 0x0800 //左边第12个数码管的com显示 #define const_left_com13 0x1000 //左边第13个数码管的com显示 #define const_left_com14 0x2000 //左边第14个数码管的com显示 #define const_left_com15 0x4000 //左边第15个数码管的com显示 #define const_left_com16 0x8000 //左边第16个数码管的com显示 #define const_left_com_off 0x0000 //所有的数码管都不显示 void display_drive(); //数码管驱动程序,放在定时中断里 void hc595_drive(unsigned int com_select); //驱动2片联级的74hc595的子程序,放在display_drive()里 void _nop_(); //驱动时序延时函数 void delay1(unsigned int de); unsigned char number_left1=0; //左边第1位数码管显示的内容 unsigned char number_left2=0; //左边第2位数码管显示的内容 unsigned char number_left3=0; //左边第3位数码管显示的内容 unsigned char number_left4=0; //左边第4位数码管显示的内容 unsigned char number_left5=0; //左边第5位数码管显示的内容 unsigned char number_left6=0; //左边第6位数码管显示的内容 unsigned char number_left7=0; //左边第7位数码管显示的内容 unsigned char number_left8=0; //左边第8位数码管显示的内容 unsigned char number_left9=0; //左边第9位数码管显示的内容 unsigned char number_left10=0; //左边第10位数码管显示的内容 unsigned char number_left11=0; //左边第11位数码管显示的内容 unsigned char number_left12=0; //左边第12位数码管显示的内容 unsigned char number_left13=0; //左边第13位数码管显示的内容 unsigned char number_left14=0; //左边第14位数码管显示的内容 unsigned char number_left15=0; //左边第15位数码管显示的内容 unsigned char number_left16=0; //左边第16位数码管显示的内容 unsigned char dis_step=1; //扫描的步骤 const unsigned char number_table[]= //数码管的字模转换表 { 0xfa, //显示"0" 0x82, //显示"1" 0xb9, //显示"2" 0xab, //显示"3" 0xc3, //显示"4" 0x6b, //显示"5" 0x7b, //显示"6" 0xa2, //显示"7" 0xfb, //显示"8" 0xeb, //显示"9" }; //主程序 main() { ADCON0=0x00; ADCON1=0x0f; //全部为数字信号 ADCON2=0xa1; //右对齐 RBPU=0; //上拉电阻 SSPEN=0; TRISA3=0; //74hc595的4根驱动IO之一 TRISA4=0; //74hc595的4根驱动IO之一 TRISA5=0; //74hc595的4根驱动IO之一 TRISD=0x00; //数码管的seg输出 T1CON=0x24; //定时器中断配置 TMR1H=0xFE; TMR1L=0xEF; TMR1IF=0; TMR1IE=1; TMR1ON=1; TMR1IE=1; while(1) { CLRWDT(); //喂看门狗,大家不用过度关注此行 number_left1=1; //左边第1位数码管显示"1" number_left2=2; //左边第2位数码管显示"2" number_left3=3; //左边第3位数码管显示"3" number_left4=4; //左边第4位数码管显示"4" number_left5=5; //左边第5位数码管显示"5" number_left6=6; //左边第6位数码管显示"6" number_left7=7; //左边第7位数码管显示"7" number_left8=8; //左边第8位数码管显示"8" number_left9=8; //左边第9位数码管显示"8" number_left10=7; //左边第10位数码管显示"7" number_left11=6; //左边第11位数码管显示"6" number_left12=5; //左边第12位数码管显示"5" number_left13=4; //左边第13位数码管显示"4" number_left14=3; //左边第14位数码管显示"3" number_left15=2; //左边第15位数码管显示"2" number_left16=1; //左边第16位数码管显示"1" } } void interrupt timer1rbint(void) //中断 { if(TMR1IE==1&&TMR1IF==1) //定时中断 { TMR1IF=0; //定时中断标志位关闭 TMR1ON=0; //定时中断开关关闭 display_drive(); //数码管驱动程序 TMR1H=0xFe; //重新设置定时时间间隔 TMR1L=0x00; TMR1ON=1; //定时中断开关打开 } } void display_drive() //数码管驱动程序,放在定时中断里 { unsigned char number_temp; //中间临时变量 switch(dis_step) { case 1: number_temp=number_table[number_left1]; //左边第1个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com1); //com选 break; case 2: number_temp=number_table[number_left2]; //左边第2个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com2); //com选 break; case 3: number_temp=number_table[number_left3]; //左边第3个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com3); //com选 break; case 4: number_temp=number_table[number_left4]; //左边第4个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com4); //com选 break; case 5: number_temp=number_table[number_left5]; //左边第5个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com5); //com选 break; case 6: number_temp=number_table[number_left6]; //左边第6个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com6); //com选 break; case 7: number_temp=number_table[number_left7]; //左边第7个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com7); //com选 break; case 8: number_temp=number_table[number_left8]; //左边第8个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com8); //com选 break; case 9: number_temp=number_table[number_left9]; //左边第9个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com9); //com选 break; case 10: number_temp=number_table[number_left10]; //左边第10个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com10); //com选 break; case 11: number_temp=number_table[number_left11]; //左边第11个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com11); //com选 break; case 12: number_temp=number_table[number_left12]; //左边第12个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com12); //com选 break; case 13: number_temp=number_table[number_left13]; //左边第13个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com13); //com选 break; case 14: number_temp=number_table[number_left14]; //左边第14个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com14); //com选 break; case 15: number_temp=number_table[number_left15]; //左边第15个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com15); //com选 break; case 16: number_temp=number_table[number_left16]; //左边第16个数码管显示的内容 PORTD=number_temp; hc595_drive(const_left_com16); //com选 break; } delay1(15); //每一位数码管显示的停留时间 hc595_drive(const_left_com_off); //让所有的数码管都不显示,让显示效果更好 PORTD=0x00; ++dis_step; //进入下一个数码管的扫描 if(dis_step>16) { dis_step=1; } } void hc595_drive(unsigned int com_select) //驱动2片联级的74hc595的子程序 { unsigned char tempdata; hc595_sh_dr=0; hc595_st_dr=0; for(tempdata=0;tempdata<16;tempdata++) { CLRWDT(); if(com_select>=0x8000)hc595_ds_dr=1; else hc595_ds_dr=0; hc595_sh_dr=0; _nop_(); _nop_(); hc595_sh_dr=1; _nop_(); _nop_(); com_select<<=1; } hc595_st_dr=0; _nop_(); _nop_(); hc595_st_dr=1; _nop_(); _nop_(); hc595_sh_dr=0; //拉低,抗干扰就增强 hc595_st_dr=0; hc595_ds_dr=0; } void _nop_() //驱动时序延时函数 { unsigned char n; for(n=0;n<0x0f;n++); } void delay1(unsigned int de) { unsigned int t; for(t=0;t (6)小结: 我知道,我的源代码如果多用一些循环,还可以书写得更加节省容量,有兴趣的 朋友请自己修改试试。 (7)下集预告: 利用74HC595静态驱动数码管。 (未完待续,下节更精彩,不要走开哦) |
|
|
|
|
|
|
|
|
|
|
|
|
|
我的第二十二节中只用了2片74HC595联级来驱动16位数码管,不是3片,可能你看错了。而且我的驱动电路跟你用2片74HC595驱动8位数码管的原理是有区别的,虽然它们都是动态扫描的方式,不过我扫数码管的SEG是直接用单片机8根IO口,扫描数码管的COM才用2片联级的74hc595来驱动,坦白的讲,这种电路我最多驱动过10位数码管,至于16位的嘛,我还没亲自上机验证过,估计刷新速度应该还能应付得过来。而你的电路是用1个74HC595扫描数码管的SEG,用另外1个74HC595扫描数码管的COM,我没试过像你这样用的,不过我觉得你这种方式很巧妙,我又从你那里学到了知识,谢谢。 |
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2076 浏览 1 评论
3489 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2329 浏览 2 评论
2754 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4012 浏览 5 评论
960浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6346浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 09:01 , Processed in 0.917862 second(s), Total 89, Slave 81 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号