搜索
bottom↓
回复: 15

成功了!4根IO口线驱动1602,带PWM调光。

[复制链接]

出0入0汤圆

发表于 2012-7-12 21:51:29 | 显示全部楼层 |阅读模式
本帖最后由 xwkm 于 2012-7-12 21:54 编辑

       呵呵,不用我说你们也知道为什么只需要4根线:因为咱用了74hc595啊!因为74HC595最近我手里一抓一大把。但是STC的单片机IO口紧缺。就算使用4线驱动模式也要8个IO(还要算上背光PWM)。这一次我几乎做到了他的一半。如果不用PWM的话。大概只需要3个IO,如果需要PWM就四个罗。
      MCU当然是老掉牙的死特惨89C52罗~
      画原理图实在是不方便。就不画了。另外求酷~
      也可以在595后面级联类似三极管开关……继电器之类的玩意。当然友情提醒,别超过4个595.否则速度会慢的可怕。我现在1个595.写1602都可以丢掉延时函数了。
       这一次硬件设计的比较简单,但是IO全反了。所以需要占用额外的CPU时间修正,但是毕竟方便洞洞板嘛。还有大家别看到我给A和B赋了好几次值而去“优化”代码。如果您“优化”的话,那么就根本驱动不起来,因为51的加法减法乘除都要经过ACC和B,如果不去重新赋值的话,那么就会发生改变的现象。不过我这种位寻址软件修正可比那种xx=xx & xx的效率高多了。如果我这么写的话。恐怕刷一个屏幕没1秒下不来啊。12T的51就这个速度……
       不过这一次焊板子实在是太仓促了。对比度电位器焊在液晶下面,结果初始化成功了显示两排方块。晕了半天。调试半天还是没用。后来捅了一下背面就好了……晕……!
       上代码:
  1. #include <stc89c5x.h>//STC89C52

  2. //串行驱动1602,powered by 595
  3. #define LCD1602_BACKLIGHT        P1_3//背光
  4. #define LCD1602_SDA                        P1_0//数据输入
  5. #define LCD1602_SCK                        P1_1//移位时钟,SHCP,11pin
  6. #define LCD1602_SCL                        P1_2//锁存时钟,STCP,12pin

  7. /*
  8. * 硬件连接:
  9. * 74HC595 Q7 - 1602 RS
  10. * GND - 1602 RW(595没有输入功能,所以判定忙只能靠延时,另外就是MCU的速度比较的慢。所以也可以直接去掉延时。但是在STC12系列上的表现,我可不知道会怎么样
  11. * 74HC595 Q6 - 1602 EN
  12. * 74HC595 Q5~Q2 - 1602 D5~D7(这一次硬件设计不合理,才只能搞软件修正了。不过好处就是直接就可以洞洞板上对着联,减少了烧坏595的概率。坏处就是CPU时间消耗的多了点。但是可以取消延时函数啦~
  13. * 1602 D1~D4 直接悬空
  14. * LCD_BACKLIGHT加一级PNP三极管射随器加到液晶的A上,如果无需调光可以去掉这一部分电路和代码
  15. * 至于595的连接,只要不弄反SCL和SCK,就没有问题啦~
  16. */

  17. __sbit  __at  0xE0 A_0;//方便位操作,硬件设置真的是败笔 - -
  18. __sbit  __at  0xE1 A_1;
  19. __sbit  __at  0xE2 A_2;
  20. __sbit  __at  0xE3 A_3;
  21. __sbit  __at  0xE4 A_4;
  22. __sbit  __at  0xE5 A_5;
  23. __sbit  __at  0xE6 A_6;
  24. __sbit  __at  0xE7 A_7;
  25. __sbit  __at  0xF1 B_1;
  26. __sbit  __at  0xF2 B_2;
  27. __sbit  __at  0xF3 B_3;
  28. __sbit  __at  0xF4 B_4;
  29. __sbit  __at  0xF5 B_5;
  30. __sbit  __at  0xF6 B_6;
  31. __sbit  __at  0xF7 B_7;

  32. unsigned char PWM_Cycle=0;//PWM占空比
  33. unsigned char PWM_T=0;//PWM当前所处周期
  34. unsigned char OutBuf=0xff;//输出缓冲
  35. #define        LCD_OFF         lcd_wcmd(0x08)
  36. #define        LCD_CUR         lcd_wcmd(0x0E)
  37. #define LCD_FCUR        lcd_wcmd(0x0F)
  38. void delay(unsigned int n)
  39. {
  40. unsigned int x,y;
  41. for(x=n;x>0;x--)
  42. for(y=100;y>0;y--);
  43. }

  44. void Send595()
  45. {
  46.         unsigned char i,j;
  47.         j=0x80;
  48.         LCD1602_SCK=0;
  49.         for(i=0;i<8;i++)
  50.         {
  51.                 LCD1602_SDA=OutBuf & j;
  52.                 j=j>>1;
  53.                 LCD1602_SCK=1;
  54.                 LCD1602_SCK=0;
  55.         }
  56.         LCD1602_SDA=1;
  57.         LCD1602_SCL=0;
  58.         LCD1602_SCL=1;
  59. }
  60. void lcd_en()
  61. {
  62.         //OutBuf=OutBuf|0x40;//E=1
  63.         B=OutBuf;
  64.         B_6=1;
  65.         OutBuf=B;
  66.         Send595();//输出数据
  67.         B=OutBuf;
  68.         B_6=0;
  69.         OutBuf=B;//E=0
  70.         Send595();
  71. }

  72. /**********************************************************/
  73. void lcd_wcmd(unsigned char i)
  74. {
  75. //写命令
  76.         B=OutBuf;
  77.         B_7=0;//RS=0,RW=0;
  78.         OutBuf=B;
  79.         Send595();
  80. //--------------
  81.         B=OutBuf;
  82.         ACC=i;
  83.         B_2=A_7;//D7=D7
  84.         B_3=A_6;//D6=D6
  85.         B_4=A_5;//D5=D5
  86.         B_5=A_4;//D4=D4
  87.         OutBuf=B;
  88.         Send595();
  89.         lcd_en();
  90. //================
  91.         ACC=i;
  92.         B=OutBuf;
  93.         B_2=A_3;//D7=D3
  94.         B_3=A_2;//D6=D2
  95.         B_4=A_1;//D5=D1
  96.         B_5=A_0;//D4=D0
  97.         OutBuf=B;       
  98.         Send595();
  99.         lcd_en();
  100. }
  101. void lcd_wdat(unsigned char i)
  102. {
  103. //写数据
  104.         B=OutBuf;
  105.         B_7=1;//RS=0,RW=0;
  106.         OutBuf=B;
  107.         Send595();
  108. //--------------
  109.         B=OutBuf;
  110.         ACC=i;
  111.         B_2=A_7;//D7=D7
  112.         B_3=A_6;//D6=D6
  113.         B_4=A_5;//D5=D5
  114.         B_5=A_4;//D4=D4
  115.         OutBuf=B;
  116.         Send595();
  117.         lcd_en();
  118. //================
  119.         ACC=i;
  120.         B=OutBuf;
  121.         B_2=A_3;//D7=D3
  122.         B_3=A_2;//D6=D2
  123.         B_4=A_1;//D5=D1
  124.         B_5=A_0;//D4=D0
  125.         OutBuf=B;       
  126.         Send595();
  127.         lcd_en();
  128. }

  129. void lcd_putchar(unsigned char addr,unsigned char ch)
  130. {//写一个字
  131.         lcd_wcmd(0x80+addr);
  132.         lcd_wdat(ch);
  133. }

  134. void lcd_display(unsigned char *l1,unsigned char *l2)
  135. {//写一屏幕
  136.         unsigned char i=0;
  137.         lcd_wcmd(0x80); //显示地址设为80H(即00H,)上排第一位
  138.         for(i=0;i<16;i++)
  139.         {
  140.                 lcd_wdat(l1[i]);
  141.         }
  142.         lcd_wcmd(0x80+0x40); //重新设定显示地址为0xc0,即下排第1位
  143.         for(i=0;i<16;i++)
  144.         {
  145.                 lcd_wdat(l2[i]);
  146.         }
  147. }

  148. void lcd_cls()
  149. {
  150.         lcd_wcmd(0x01); //清屏延时函数可以省略
  151. }
  152. //米有读函数,但是功能可以由上面的函数扩展哦~
  153. void lcd_init()
  154. {

  155.         lcd_wcmd(0x20);
  156.         lcd_en();//唤醒
  157.         lcd_wcmd(0x28); //四位,5x7
  158.         lcd_wcmd(0x0c); //开启显示屏,关光标,光标不闪烁
  159.         lcd_wcmd(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
  160.         lcd_wcmd(0x01); //清屏       
  161.         //调试的时候被设计失误的对比度电位器坑死了:就是两排小方块死都不显示
  162.         //查了半天都不知道
  163.         //最后捅了下电位器就正常了……
  164. }
  165. void PWM() __interrupt 1 __using 1
  166. {
  167.         ET0=0;
  168.         TF0=0;//CLR
  169.         TR0=0;
  170.         EA=0;
  171.         TH0=0xFC;TL0=0x00;//十级调光,频率400Hz
  172.         if(PWM_T>10) {PWM_T=0;}
  173.         if(PWM_Cycle>PWM_T){ LCD1602_BACKLIGHT=0;}
  174.         if(PWM_Cycle<PWM_T)  {LCD1602_BACKLIGHT=1;}
  175.         PWM_T++;
  176.         TR0=1;
  177.         ET0=1;
  178.         EA=1;
  179. }

  180. void main()
  181. {//主函数

  182.         TMOD = 0x01 ;
  183.         TH0=0xFC;TL0=0x00;
  184.         TR0=1;ET0=1;
  185.         EA=1;//开中断
  186.         //-----------------
  187.         lcd_init();
  188.         PWM_Cycle=10;//背光100%
  189.         //液晶初始化---------
  190.         while(1)
  191.         {
  192.                 lcd_display("  Hello world!  ","Serial mode 1602");
  193.                 delay(2000);
  194.                 lcd_display("Drive by 74HC595","Design by rgwan ");
  195.                 delay(2000);
  196.                 lcd_display("Website address:"," www.rwzy.co.cc ");
  197.                 delay(2000);
  198.                 lcd_display("Backlight Ctl by","  T0 PWM 400Hz  ");
  199.                 delay(2000);
  200.         }
  201. }

复制代码
补上低清无码ImageMagick压制图……





自己DIY的最小系统,旁边是串口转接器。这个板子上有两个晶振跳线选择
外加一个外界晶振。现在这个晶振跳在内置的11.0592上。



背面,没布局好,那飞线……
接口在左边是GND,VCC,BACKLIGHT.前面是SCK SCL SDA.
万致远原创。第二发于amoBBS(OURDEV)转载请注明出处~
下一次做一个串行驱动12864……

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-7-12 22:00:41 | 显示全部楼层
顶一个!!

出0入0汤圆

发表于 2012-7-12 22:25:20 | 显示全部楼层
lz 可以去看下 cowboy的,只要2个io驱动1602。。。

出0入0汤圆

发表于 2012-7-12 22:27:44 | 显示全部楼层
当然,总结一下几个方案:
2个io+cowboy阻容电路
2片74164,也是2个io驱动,
3个io+2片595,亦可

出0入0汤圆

 楼主| 发表于 2012-7-12 22:31:52 | 显示全部楼层
本帖最后由 xwkm 于 2012-7-12 22:32 编辑
wkman 发表于 2012-7-12 22:27
当然,总结一下几个方案:
2个io+cowboy阻容电路
2片74164,也是2个io驱动,


我用了一个595~
3个IO+一个595一样行。
如果不考虑利用率的话。
可以把 SCK和SCL短上。程序再次改动一下。就OK啦~
所以刚才实验两个IO+一个595也行。就是程序要改动一下。加上调背光就三个IO

出0入54汤圆

发表于 2012-7-13 14:49:00 | 显示全部楼层
厉害!PFPFPFPF

出0入0汤圆

发表于 2012-7-13 15:15:15 | 显示全部楼层
如果你的桌子是真实木的话,桌子远比你的这个设计更给力。
好象不是真实木的。

出0入0汤圆

发表于 2012-7-13 15:57:50 | 显示全部楼层
莫非不能像avr那样直接用四线驱动起来?刚接触51不懂

出0入0汤圆

 楼主| 发表于 2012-7-15 00:39:27 | 显示全部楼层
fwluck 发表于 2012-7-13 15:15
如果你的桌子是真实木的话,桌子远比你的这个设计更给力。
好象不是真实木的。 ...


对不起,是真的实木……
我爸自己买木料操刀设计的……
钉子的痕迹都有。还有,你歪搂了……

出0入0汤圆

发表于 2012-7-19 21:16:30 | 显示全部楼层
给楼主赞一个

出0入0汤圆

发表于 2013-9-7 18:24:31 | 显示全部楼层
非常不错,收藏了,谢谢

出0入0汤圆

发表于 2013-9-7 18:55:38 | 显示全部楼层
the code is very difficult to port and risky because of the use of ACC / B.

some suggestions:

  1. __sbit  __at  0xE0 A_0;//方便位操作,硬件设置真的是败笔 - -
  2. __sbit  __at  0xE1 A_1;
  3. __sbit  __at  0xE2 A_2;
  4. __sbit  __at  0xE3 A_3;
  5. __sbit  __at  0xE4 A_4;
  6. __sbit  __at  0xE5 A_5;
  7. __sbit  __at  0xE6 A_6;
  8. __sbit  __at  0xE7 A_7;
  9. __sbit  __at  0xF1 B_1;
  10. __sbit  __at  0xF2 B_2;
  11. __sbit  __at  0xF3 B_3;
  12. __sbit  __at  0xF4 B_4;
  13. __sbit  __at  0xF5 B_5;
  14. __sbit  __at  0xF6 B_6;
  15. __sbit  __at  0xF7 B_7;
复制代码
no need for any of that.
  1. void Send595()
复制代码
Provide a parameter to Send595 to simply it

  1. void lcd_en()
复制代码
consider routing LCD_EN separately.
  1. void lcd_wcmd(unsigned char i)
复制代码
it is overly complicated, because of the way you set up your hardware.

I would adopt an approach that allows you to do either 4 or 8 bit wiring to the lcd.

出0入0汤圆

发表于 2013-10-12 22:46:14 | 显示全部楼层
支持楼主

出0入0汤圆

发表于 2013-10-12 23:12:44 | 显示全部楼层
马克一下 哈

出0入0汤圆

发表于 2013-10-12 23:13:12 | 显示全部楼层
马克一下 哈   

出0入0汤圆

发表于 2013-10-15 21:40:41 | 显示全部楼层
你的电路焊接的够可以的。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 16:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表