找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2100|回复: 14
收起左侧

STC8A单片机用I2C扩展IO口芯片不知道问题出在哪里,新年快乐

[复制链接]
ID:1022674 发表于 2023-1-29 18:34 | 显示全部楼层 |阅读模式
这个程序就是测试一下单片机的I2C程序,能不能和IO口扩展芯片通讯使用。
各位大老,不知道问题出在哪里,烧进去没反应,接触单片机时间不长,望大老有时间帮忙看看,在这里谢谢了!新年快乐!

单片机源程序如下:
  1. #include<reg52.h>
  2. #include "intrins.h"
  3. #define unit unsigned int
  4. #define uchar unsigned char
  5.         
  6. #define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)
  7. #define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81)
  8. #define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
  9. #define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
  10. #define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
  11. #define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
  12. #define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
  13. #define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)

  14. #define  i2cl  0x44          //定义前提命令 -发送低8位IO口数据
  15. #define  i2ch  0x46         //定义前提命令 -发送高8位IO口数据

  16. unsigned int u=0;v=0;x=0; y=0; m=0;w=0;
  17. static unsigned char  a,b,d,e,f,g,h,i,c,i2clh,i2cdata;

  18. sfr     P0M0        =   0x94;
  19. sfr     P0M1        =   0x93;
  20. sfr     P1M0        =   0x92;
  21. sfr     P1M1        =   0x91;
  22. sfr     P2M0        =   0x96;
  23. sfr     P2M1        =   0x95;
  24. sfr     P3M0        =   0xb2;
  25. sfr     P3M1        =   0xb1;
  26. sfr     P4M0        =   0xb4;
  27. sfr     P4M1        =   0xb3;
  28. sfr     P5M0        =   0xca;
  29. sfr     P5M1        =   0xc9;
  30. sfr     P6M0        =   0xcc;
  31. sfr     P6M1        =   0xcb;
  32. sfr     P7M0        =   0xe2;
  33. sfr     P7M1        =   0xe1;


  34. sfr  P4  = 0xc0;
  35. sfr  P5  = 0xc8;
  36. sfr  P6  = 0xe8;
  37. sfr  P7  = 0xf8;


  38. sfr     P_SW2       =   0xba;

  39. sbit k1=P7^3;                    //高/低位数据选择开关
  40. sbit k2=P2^0;                    //点动测试开关,数据有变化I2C就发送新的数据到IO扩展IC
  41. sbit k14=P4^2;                  //清零开关

  42. bit busy;                            //I2C中断标志位

  43. void timer0Init()                //中断时间计数器函数
  44. {
  45. TMOD|=0x01;
  46. TH0=0xFF;
  47. TL0=0xA3;
  48. ET0=1;
  49. EA=1;
  50. TR0=1;
  51. }

  52. void Timer0() interrupt 1               //程序运行依赖-中断函数
  53. {
  54.                           TH0=0xFF;
  55.                           TL0=0xA3;
  56.                
  57.                           y++;               
  58.                           u++;               
  59.                           v++;               
  60.                           ys++;
  61.                                                    
  62.                           if(k2==0||k14==0)
  63.                             {x++; }                                                                                                                                       
  64. }

  65. void I2C_Isr() interrupt 24                        //I2C中断函数-清零
  66. {
  67.     char store;

  68.     store = P_SW2;
  69.     P_SW2 |= 0x80;
  70.     if (I2CMSST & 0x40)
  71.     {
  72.         I2CMSST &= ~0x40;                       //清中断标志
  73.         busy = 0;
  74.     }
  75.     P_SW2 = store;
  76. }

  77. //_______________________________       I2C各命令子函数
  78. void Start()
  79. {
  80.     busy = 1;
  81.     I2CMSCR = 0x81;                             //发送START命令
  82.     while (busy);
  83. }

  84. void SendData(char dat)
  85. {
  86.     I2CTXD = dat;                               //写数据到数据缓冲区
  87.     busy = 1;
  88.     I2CMSCR = 0x82;                             //发送SEND命令
  89.     while (busy);
  90. }

  91. void RecvACK()
  92. {
  93.     busy = 1;
  94.     I2CMSCR = 0x83;                             //发送读ACK命令
  95.     while (busy);
  96. }

  97. void Stop()
  98. {
  99.     busy = 1;
  100.     I2CMSCR = 0x86;                             //发送STOP命令
  101.     while (busy);
  102. }
  103. //_________________________

  104. void i2c(char aa,char  bb)         //数据发送完整流程函数
  105. {
  106.         Start();                        //启动
  107.         SendData(aa);              //发数据1  --设置命令
  108.         RecvACK();                  //应答1
  109.         SendData(bb);              //发数据2  --驱动数据
  110.         RecvACK();                  //应答2
  111.         Stop();                          //停止
  112. }

  113. void cx1()
  114. {
  115.         e=c;f=d;
  116.         
  117.         if(k1==0)                                                         //高8位数据+1
  118.           {if(k2==0&&x>50){while(!k2);c++;x=0;}}       //x>50-为开关消抖

  119.         if(k1==1)                                                        //低8位数据+1
  120.           {if(k2==0&&x>50){while(!k2);d++;x=0;}}                                

  121.         if(k14==0&&x>50)                    //按键清零
  122.           {while(!k14);c=d=e=f=x=0;}        
  123.                         
  124.         if(e!=c){i2c(i2cl,c);}                       //高8位数据有变化就发送到IO扩展芯片
  125.         
  126.         if(f!=d){i2c(i2ch,d);}                 //低8位数据有变化就发送到IO扩展芯片
  127.                         
  128.         if(c>8){c=e=0;}      //超过8位,清零
  129.                         
  130.         if(d>8){d=f=0;}      //超过8位,清零
  131. }

  132. main()
  133. {
  134.          
  135.         timer0Init();
  136.         
  137.          
  138.   P_SW2 = 0x90;                             //使能I2C主机模式-并配置I2C脚位
  139.   I2CCFG = 0xe0;                              //使能I2C主机模式
  140.   I2CMSST = 0x00;

  141.   i2c(0x48,0x10);                             //IO扩展芯片配置清零
  142.          
  143.   P0=P1=P6=0x00; P2=P7=0x0F; P3=0xE2; P4=0x06;P5=0x03;
  144.          
  145.     P0M0 = 0x00;                                //设置P0.0~P0.7为准双向口模式
  146.     P0M1 = 0x00;
  147.     P1M0 = 0x00;                                //设置P1.0~P1.7为准双向口模式
  148.     P1M1 = 0x00;
  149.     P2M0 = 0x00;                                //设置P2.0~P2.7为准双向口模式
  150.     P2M1 = 0x00;
  151.     P3M0 = 0x00;                                //设置P3.0~P3.7为准双向口模式
  152.     P3M1 = 0x00;
  153.     P4M0 = 0x00;                                //设置P4.0~P4.7为准双向口模式
  154.     P4M1 = 0x00;
  155.     P5M0 = 0x00;                                //设置P5.0~P5.7为准双向口模式
  156.     P5M1 = 0x00;
  157.     P6M0 = 0x00;                                //设置P6.0~P6.7为准双向口模式
  158.     P6M1 = 0x00;
  159.     P7M0 = 0x00;                                //设置P7.0~P7.7为准双向口模式
  160.     P7M1 = 0x00;
  161.     a=0;
  162.     b=0;
  163.     c=0;
  164.     i=0;

  165.    while(1)
  166.   {                  
  167.          cx1();
  168.   }
  169. }        
复制代码

两线远程 IO 扩展芯片 CH423.pdf

203.17 KB, 下载次数: 6

回复

使用道具 举报

ID:1022674 发表于 2023-1-29 18:38 | 显示全部楼层
调试时,发现会在Start()启动函数下, while (busy); 这里卡住,难道是没有进入I2C中断里清零?如果是这样,那为什么没有进入I2C中断呢?希望各位大老指教!新年快乐!
回复

使用道具 举报

ID:401564 发表于 2023-1-29 21:47 | 显示全部楼层
新手别搞这些量大的代码
STC8A不需要端口扩展,你用都用不完
如果是想学习一下IIC,那就必须得是24C01不可了
单片机学习本身就是通过抄别人的代码来提升自己,从而达到别人也要抄你代码的高度
回复

使用道具 举报

ID:1034262 发表于 2023-1-29 23:16 | 显示全部楼层
示波器先看一下I2C有输出吗?
直接测试STC官方例程可以吗?
回复

使用道具 举报

ID:1022674 发表于 2023-1-30 09:46 | 显示全部楼层
Y_G_G 发表于 2023-1-29 21:47
新手别搞这些量大的代码
STC8A不需要端口扩展,你用都用不完
如果是想学习一下IIC,那就必须得是24C01不可 ...

哦,谢谢!受教了。新年快乐!
回复

使用道具 举报

ID:1022674 发表于 2023-1-30 09:47 | 显示全部楼层
coody_sz 发表于 2023-1-29 23:16
示波器先看一下I2C有输出吗?
直接测试STC官方例程可以吗?

我测一下,谢谢!新年快乐!
回复

使用道具 举报

ID:1010435 发表于 2023-1-30 10:49 | 显示全部楼层
建议先用针脚模拟I2C,网上大把的成品函数,理解各个函数的作用和时序后,再用硬件I2C驱动,
回复

使用道具 举报

ID:1022674 发表于 2023-1-30 14:42 | 显示全部楼层
mtt661 发表于 2023-1-30 10:49
建议先用针脚模拟I2C,网上大把的成品函数,理解各个函数的作用和时序后,再用硬件I2C驱动,

模拟I2C,之前有试过,现在想用单片机的硬件I2C试试,问题好像是数据不发送,也进不了I2C的中断函数,然后卡在那里。
回复

使用道具 举报

ID:1022674 发表于 2023-1-30 14:50 | 显示全部楼层
wjq0312 发表于 2023-1-30 09:47
我测一下,谢谢!新年快乐!

没有输出,官方示例也没有输出,问题好像是数据命令不发送,然后就不会有中断请求,所以就进不了I2C的中断函数,然后卡在那里。真奇怪,给发送缓冲区数据为什么不会发送。
回复

使用道具 举报

ID:624769 发表于 2023-1-30 23:07 | 显示全部楼层
wjq0312 发表于 2023-1-30 14:50
没有输出,官方示例也没有输出,问题好像是数据命令不发送,然后就不会有中断请求,所以就进不了I2C的中 ...

具体型号,具体版本,
STC8A  分  STC8A8K64D4(新)    和  STC8A8K64S4A12(旧) 这两种
实际使用中 STC8A8K64D4(新)  有部分芯片,使用 I2C 中断方式  会莫名失败。即开了中断I2C 就不工作。或者,会莫名不触发中断,但是查询方式一切正常。 而 STC8A8K64S4A12(旧) 则没有这个问题。假如你用的STC8A8K64D4(新) 建议你直接改成查询方式操作,看你的代码,你中断方式 也是傻等,和查询其实没有差别。
回复

使用道具 举报

ID:1022674 发表于 2023-1-31 10:49 | 显示全部楼层
188610329 发表于 2023-1-30 23:07
具体型号,具体版本,
STC8A  分  STC8A8K64D4(新)    和  STC8A8K64S4A12(旧) 这两种
实际使用中 STC8A8 ...

哦,好的,谢谢大老!新年快乐!
回复

使用道具 举报

ID:1022674 发表于 2023-1-31 11:06 | 显示全部楼层
188610329 发表于 2023-1-30 23:07
具体型号,具体版本,
STC8A  分  STC8A8K64D4(新)    和  STC8A8K64S4A12(旧) 这两种
实际使用中 STC8A8 ...

就是你说的STC8A8K64D4这个型号,谢谢解惑!
回复

使用道具 举报

ID:975054 发表于 2023-8-31 14:53 | 显示全部楼层
今天碰到个问题还没解决:
之前一直用20脚的STC8G1K08的I2C很正常;
近来简化为8脚STC8G1K08A后,就不正常!说明如下:
选I2C脚为P54P55(设置为开漏串300Ω到I2C外设,特殊原因,我MCU电池供电,I2C模块3.3V,得匹配), 引脚功能切换设置P_SW2 |= 0X10,按手册应该没错,其他初始化及外设一概没变;I2C就是不能正常运行。
回复

使用道具 举报

ID:975054 发表于 2023-9-1 18:34 | 显示全部楼层
ax6808 发表于 2023-8-31 14:53
今天碰到个问题还没解决:
之前一直用20脚的STC8G1K08的I2C很正常;
近来简化为8脚STC8G1K08A后,就不正常 ...

今天再次摸查情况: STC8的I2C时钟脚我设为开漏输出禁止输入了,外部有10K上拉电阻, 原来是:我设置为允许输入后,I2C居然能正常工作了。之前I2C和MCU电平匹配设为双向置1时,这个脚可以禁止输入的。
回复

使用道具 举报

ID:975054 发表于 2023-9-2 19:30 | 显示全部楼层
ax6808 发表于 2023-9-1 18:34
今天再次摸查情况: STC8的I2C时钟脚我设为开漏输出禁止输入了,外部有10K上拉电阻, 原来是:我设置为允许输 ...

看了有关文章,启发很大!总之:而脚都得默认允许输入!
之前我MCU有硬件I2C口,只接一个共用3.3V电源的从机,MCU二脚可设置为双向置1,SCL可以禁止输入,工作很正常的(其实可能不够可靠)。后来改为不共用电源后,已设置为开漏,外部有上拉电阻,结果就不正常了。后来检查发现这种情况SCL就得设置回默认的允许输入才行!可能是有些代码变了响应不及时,SCL禁止输入主机就探测不到被拉低了所以出错!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

Powered by 单片机教程网

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