单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:5590|回复:2
打印上一主题下一主题

发一个PCF8574A I2C接口的1602程序.欢迎各路大侠指点

[复制链接]
跳转到指定楼层
楼主
ID:105672发表于 2016-2-18 14:41|只看该作者回帖奖励
拆了一台点钞机,主控板是用STC的12C5A16AD,正好手有块I2C的LCD1602.无聊就搞搞实验,用定时器做了个时钟.
  1. #include< STC15F104E.H>
  2. #include< intrins.h>
  3. sbit SDA=P0^2;    
  4. sbit SCL=P0^1;

  5. bit ack,blk;       //I2C 应答位  LCD背光开关

  6. #define uchar unsigned char                                  
  7.                                                                                     
  8.                                                                                     
  9. uchar num[]={"0123456789"},sec,min,hou;
  10. unsigned int us,ms;





  11. #define WriteAdd     0x7e         //写PCF8574A地址 0111 A2 A2 A0 W
  12. #define ReadAdd     0x7f           //读PCF8574A地址 0111 A2 A2 A0 R
  13.                                                                          //             背光   CS/EN  R/W  RS
  14.                          //P7 P6 P5 P4 P3 P2     P1   P0  PCF8574A引脚
  15. //#define WriteCom               8                     //DB7  DB6  DB5  DB4  1     0         0   0     RW=0写   RS=0指令  BLK背光
  16. //#define WriteData               9                   //DB7  DB6  DB5  DB4  1     0         0   1     RW=0写   RS=1数据
  17. //#define WriteComEn           0x0c               //DB7  DB6  DB5  DB4  1     1         0   0     RW=0写   RS=0
  18. //#define WriteDataEn           0x0d             //DB7  DB6  DB5  DB4  1     1         0   1     RW=0写   RS=1数据

  19. /*========================  PCF8574A  P3 = 0 关背光   ====================================*/

  20. //#define WriteCom               0                     //DB7  DB6  DB5  DB4  0     0         0   0     RW=0写   RS=0指令  BLK背光
  21. //#define WriteData               1                     //DB7  DB6  DB5  DB4  0     0         0   1     RW=0写   RS=1数据
  22. //#define WriteComEn           4                 //DB7  DB6  DB5  DB4  0     1         0   0     RW=0写   RS=0
  23. //#define WriteDataEn           5                 //DB7  DB6  DB5  DB4  0     1         0   1     RW=0写   RS=1数据

  24. uchar WriteCom=8,WriteData=9,WriteComEn=0x0c,WriteDataEn=0x0d;

  25. void LcdBlk()                                 //LCD背光控制 blk=1亮,blk=0灭
  26.      {
  27.          if (blk) {WriteCom=8,WriteData=9,WriteComEn=0x0c,WriteDataEn=0x0d;}
  28.                  else {WriteCom=0,WriteData=1,WriteComEn=4,WriteDataEn=5;}
  29.      }

  30. void Delayms()         //@22.1184MHz 1MS
  31. {
  32.      unsigned char i, j;

  33.      i = 22;
  34.      j = 128;
  35.      do
  36.      {
  37.          while (--j);
  38.      } while (--i);
  39. }
  40. void Timer0Init(void)         //10微秒@22.1184MHz     定时器做时钟
  41. {
  42.      AUXR |= 0x80;         //定时器时钟1T模式
  43.      TMOD& = 0xF0;         //设置定时器模式
  44.      TMOD |= 0x02;         //设置定时器模式
  45.      TL0 = 0x23;         //设置定时初值
  46.      TH0 = 0x23;         //设置定时重载值
  47.      TF0 = 0;         //清除TF0标志
  48.      TR0 = 1;         //定时器0开始计时
  49.      ET0=1;EA=1;
  50. }

  51. void Delay5us()         //@22.1184MHz
  52. {
  53.      unsigned char i;

  54.      _nop_();
  55.      _nop_();
  56.      _nop_();
  57.      i = 24;
  58.      while (--i);
  59. }
  60. void i2cStart()                 //I2C 起始信号
  61. {
  62.    SDA=1; _nop_();  SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_();   SDA=0; _nop_(); _nop_(); _nop_();_nop_(); _nop_();SCL=0;Delay5us();    
  63. }

  64. void i2cStop()                 //I2C 停止信号
  65. {
  66.   SDA=0; _nop_();  SCL=1;  _nop_();  _nop_();  _nop_();  _nop_();  _nop_();  SDA=1;  _nop_();  _nop_();  _nop_();  _nop_();
  67. }

  68. void i2cAck(bit a)   //I2C应答信号
  69. {
  70. if(a==0)SDA=0;             //在此发出应答或非应答信号
  71. else SDA=1;
  72. _nop_();
  73. _nop_();
  74. _nop_();
  75. SCL=1;
  76. Delay5us();
  77. SCL=0;                         //清时钟线,钳住I2C 总线以便继续接收
  78. Delay5us();
  79. }

  80. void i2cWriteByte(uchar temp)                 //I2C写一字节
  81. {
  82.    uchar i;
  83.   for(i=0;i<8;i++)
  84.   {
  85.                SDA=(bit)(temp& 0x80) ;
  86.                temp<< =1; Delay5us();    
  87.                SCL=1;     Delay5us();     Delay5us();            
  88.          SCL=0;//Delay5us();
  89.      }
  90.                  _nop_();
  91.                  SDA=1;     _nop_();Delay5us();
  92.                  SCL=1;Delay5us();_nop_();_nop_();
  93.                  if(SDA==1)ack=0;
  94.                  else ack=1;                     //判断是否接收到应答信号
  95.                  SCL=0;
  96.               
  97.                         
  98. }

  99. void LcdCom(uchar com)                                     //LCD1602写指令
  100. {
  101.      i2cStart();                                                                     //I2C起始信号
  102.      i2cWriteByte(WriteAdd);                                             //PCF8574A写地址
  103.      i2cWriteByte((com&0xf0)|WriteCom);                   //先写LCD1602高4位指令+控制位
  104.      i2cWriteByte((com&0xf0)|WriteComEn);                 //LCD1602  CS/EN拉高送入
  105.      i2cWriteByte((com&0xf0)|WriteCom);                     //LCD1602  CS/EN拉低准备写入
  106.      com<<=4;                                                                         //指令低4位左移到高4位
  107.      i2cWriteByte((com&0xf0)|WriteCom);                     //写入剩下的4位指令+控制位
  108.      i2cWriteByte((com&0xf0)|WriteComEn);
  109.      i2cWriteByte((com&0xf0)|WriteCom);
  110.      i2cStop();Delay5us();                                                 //写完成,I2C停止信号
  111. }
  112. void LcdIni()                                                                     //1602初始化
  113.      {
  114.              LcdCom(0x33);
  115.              LcdCom(0x32);
  116.              LcdCom(0x28);
  117.              LcdCom(0x0c);
  118.              LcdCom(0x01);
  119.              LcdCom(0x80);
  120.      }
  121. void LcdData(uchar com)                                                 //LCD1602写数据
  122. {
  123.      i2cStart();                                                                     //I2C起始信号
  124.      i2cWriteByte(WriteAdd);                                             //PCF8574A写地址
  125.      i2cWriteByte((com&0xf0)|WriteData);                     //Delay5us();//先写LCD1602高4位指令+控制位
  126.      i2cWriteByte((com&0xf0)|WriteDataEn);                 //Delayms();//LCD1602  CS/EN接高送入
  127.      i2cWriteByte((com&0xf0)|WriteData);                     //LCD1602  CS/EN拉低准备写入
  128.      com<<=4;                                                                         //Delay5us();//数据低4位左移到高4位
  129.      i2cWriteByte((com&0xf0)|WriteDataEn);                 //Delayms();//写入剩下的4位数据+控制位
  130.      i2cWriteByte((com&0xf0)|WriteData);                     //写完成,I2C停止信号
  131.      i2cStop();Delay5us();
  132. }
  133. void LcdDisplay(uchar x,uchar *s)                             //1602显示字符串  //x=1显示在第一行,x=2显示在第二行
  134. {
  135.          if(x==1)         //第一行
  136.                  {            
  137.                      LcdCom(0x80);                                                 //第一行起始位置地址
  138.                      while(*s)
  139.                      {
  140.                          LcdData(*s);s++;
  141.                      }
  142.                  }
  143.          if(x==2)         //第二行
  144.                  {            
  145.                      LcdCom(0xc0);                                                 //第二行起始位置地址
  146.                      while(*s)
  147.                      {
  148.                          LcdData(*s);s++;
  149.                      }
  150.                  }
  151. }

  152. void main()
  153. {
  154.      Timer0Init();
  155.      LcdIni();

  156.     
  157. //     LcdDisplay(1,"  I LOVE YOU!");LcdDisplay(2," Do U Love Me?");
  158.     
  159.      while(1)
  160.         
  161.      {

  162.          LcdCom(0x80);    
  163.          if(hou>=24) {hou=0;}    
  164.          if(sec>=60) {sec=0;min++;blk=~blk;}
  165.          LcdBlk();
  166.      if(min>=60) {min=0;hou++;}
  167.              LcdData(num[hou/10]);LcdData(num[hou%10]);     LcdData(':');
  168.              LcdData(num[min/10]);LcdData(num[min%10]);LcdData(':');
  169.              LcdData(num[sec/10]);LcdData(num[sec%10]);

  170.      }


  171.         
  172. }
  173. void InterruptT0 () interrupt 1
  174. {
  175.      us++;
  176.      if (us>=100)
  177.          {
  178.              us=0;
  179.              ms++;
  180.          }    
  181.      if(ms>=1000)
  182.          {
  183.              ms=0;
  184.              sec++;
  185.          }


  186.     
  187. }
复制代码



评分

黑币 +120
收起理由
+ 15
赞一个!
+ 5
赞一个!
+ 100
共享资料的黑币奖励!

查看全部评分

沙发
ID:112693发表于 2017-4-25 23:03|只看该作者
程序是不是有问题??

Build target '目标 1'
linking...
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
   SEGMENT: ?PR?DELAYMS?1602
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
   SEGMENT: ?PR?I2CACK?1602
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
   SEGMENT: ?PR?_LCDDISPLAY?1602
Program Size: data=32.3 xdata=0 code=778
creating hex file from "1602"...
"1602" - 0 Error(s), 3 Warning(s).
板凳
ID:749957发表于 2020-5-12 16:14|只看该作者
谢谢分享

小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网