amobbs.com 阿莫电子论坛

 找回密码
 注册
bottom↓
查看: 964|回复: 14

STC8G1K12-20pin,硬件I2C读取数据总是FF,请帮我看看哪有错误?

[复制链接]
发表于 2020-3-15 01:42:07 | 显示全部楼层 |阅读模式
本帖最后由 jinlei6394 于 2020-3-16 01:35 编辑

问题解决了,是STC8G1K12的新特性导致的。

QQ图片20200316013105.png

悬空输入下,自然读不到正确的数字了...
改一下就好了。


  1. void I2C_init()
  2. {
  3.         //引脚设为准双向口
  4.         GPIO_QUASI_TWO_WAY(1, 5);
  5.         GPIO_QUASI_TWO_WAY(1, 4);
  6.        
  7.         //I2C 使用第一组(00)引脚
  8.         P_SW2 = SET_BIT_0(P_SW2, 4);
  9.         P_SW2 = SET_BIT_0(P_SW2, 5);

  10.         I2CCFG |= ENI2C; //使能I2C主机模式
  11.         I2CCFG |= MSSL;  //主机模式
  12.         I2CCFG &= ~B00111111;
  13.         I2CCFG += 63; //(63)*2+1倍时钟,大概127*0.1/3=4.23us,最大设置为(63),@30M

  14.     I2CMSST = 0x00;
  15. }
复制代码


=============================================================


这几天买了个STC8G1K12-20pin想玩玩看,
硬件I2C看上去很简单,但是怎么都搞不定,收到的数据全是FF。
换成模拟版本的I2C,同样的引脚(SDA=P14, SCL=P15)就很流畅,收发数据完全正常。
请帮我看看我代码哪有错?

时钟频率:30MHZ



  1. // i2c.c

  2. #include "common.h"
  3. #include "i2c.h"

  4. #define SCL P15
  5. #define SDA P14

  6. void Wait()
  7. {
  8.     while (!(I2CMSST & 0x40));
  9.     I2CMSST &= ~0x40;
  10. }

  11. void I2C_init()
  12. {
  13.     //I2C 打开EAXFR
  14.     P_SW2 |= 0x80;
  15.     //P_SW2 = SET_BIT_1(P_SW2, 7);
  16.        
  17.     //I2C 使用第一组(00)引脚
  18.     P_SW2 &= ~B00110000; //#define B00110000 0x30
  19.     //P_SW2 = SET_BIT_0(P_SW2, 4);
  20.     //P_SW2 = SET_BIT_0(P_SW2, 5);

  21.     I2CCFG |= ENI2C; //使能I2C主机模式
  22.     I2CCFG |= MSSL;  //主机模式
  23.     I2CCFG &= ~B00111111; //#define B00111111 0x3F
  24.     I2CCFG += 63; //(63)*2+1倍时钟,大概127*0.1/3=4.23us,最大设置为(63),@30M
  25.     //这个数字试过0,1,5,15,30,反正设成几都一样的...

  26.     I2CMSST = 0x00;
  27. }

  28. /*******I2C总线启动函数*************/
  29. void I2C_Start()
  30. {
  31.     I2CMSCR = 0x01;                             //发送START命令
  32.     Wait();
  33. }

  34. /*******I2C总线停止函数*************/
  35. void I2C_Stop()
  36. {
  37.     I2CMSCR = 0x06;                             //发送STOP命令
  38.     Wait();
  39. }

  40. /********I2C总线应答函数***********/
  41. void I2C_Send_ACK()
  42. {
  43.     I2CMSST = 0x00;                             //设置ACK信号
  44.     I2CMSCR = 0x05;                             //发送ACK命令
  45.     Wait();
  46. }

  47. /*******I2C总线非应答函数*************/
  48. void I2C_Send_NAK()
  49. {
  50.     I2CMSST = 0x01;                             //设置NAK信号
  51.     I2CMSCR = 0x05;                             //发送ACK命令
  52.     Wait();
  53. }

  54. /*********I2C总线应答检查函数*********/
  55. void I2C_Recv_ACK()
  56. {
  57.     I2CMSCR = 0x03;                             //发送读ACK命令
  58.     Wait();
  59. }

  60. /********I2C总线单字节写函数************/
  61. void I2C_SendByte(char dat)
  62. {
  63.     I2CTXD = dat;                               //写数据到数据缓冲区
  64.     I2CMSCR = 0x02;                             //发送SEND命令
  65.     Wait();
  66. }

  67. /*********I2C总线单字节读函数*************/
  68. char I2C_RecvByte()
  69. {
  70.     I2CMSCR = 0x04;                             //发送RECV命令
  71.     Wait();
  72.     return I2CRXD;
  73. }

  74. void I2C_RecvBytes(char* buf, int write_n)
  75. {
  76.         for( ; write_n>0; write_n--)
  77.         {
  78.                 *buf=I2C_RecvByte();         //开始逐个读出字节
  79.                 buf++;
  80.                 if(write_n>1)
  81.                         I2C_Send_ACK();                         //应答
  82.                 else
  83.                         I2C_Send_NAK();             //总线非应答
  84.         }
  85. }

  86. void I2C_SendBytes(char* buf, int write_n)
  87. {
  88.         for( ; write_n>0; write_n--)
  89.         {
  90.                 I2C_SendByte(*buf);         //开始逐个读出字节
  91.                 buf++;
  92.                 I2C_Recv_ACK();
  93.                 //if(F0)
  94.                 //        break;
  95.         }
  96. }
复制代码


  1. //ds3231.c

  2. #include "common.h"
  3. #include "i2c.h"
  4. #include "ds3231.h"
  5. #include "uart_test.h"

  6. #define DS3231_WriteAddress 0xD0    //器件写地址
  7. #define DS3231_ReadAddress  0xD1    //器件读地址

  8. #define REG_SEC                0x00
  9. #define REG_MIN                0x01
  10. #define REG_HOUR        0x02
  11. #define REG_DOW                0x03
  12. #define REG_DATE        0x04
  13. #define REG_MON                0x05
  14. #define REG_YEAR        0x06
  15. #define REG_CON                0x0e
  16. #define REG_STATUS        0x0f
  17. #define REG_AGING        0x10
  18. #define REG_TEMPM        0x11
  19. #define REG_TEMPL        0x12

  20. #define SEC_1970_TO_2000 946684800

  21. void gpio_i2c_write(uchar addr, uchar dat)
  22. {
  23.         I2C_Start();
  24.         I2C_SendByte(DS3231_WriteAddress);
  25.         I2C_Recv_ACK();
  26.         I2C_SendByte(addr);
  27.         I2C_Recv_ACK();
  28.         I2C_SendByte(dat);
  29.         I2C_Recv_ACK();
  30.         I2C_Stop();
  31. }

  32. uchar gpio_i2c_read(uchar addr)
  33. {
  34.     uchar dat;
  35.        
  36.         I2C_Start();
  37.         I2C_SendByte(DS3231_WriteAddress);
  38.         I2C_Recv_ACK();
  39.         I2C_SendByte(addr);
  40.         I2C_Recv_ACK();
  41.        
  42.         I2C_Start();
  43.         I2C_SendByte(DS3231_ReadAddress);
  44.         I2C_Recv_ACK();
  45.         dat = I2C_RecvByte();  //就这个dat,读出来的永远是0xFF
  46.         I2C_Send_NAK();
  47.         I2C_Stop();
  48.         return dat;
  49. }

  50. char get_one_info(uchar addr)
  51. {
  52.         uchar r, temp;
  53.         r = gpio_i2c_read(addr);
  54.         //把BCD码转换成十进制数据
  55.         temp = r / 16;
  56.         r %= 16;
  57.         r += temp * 10;
  58.         return r;
  59. }

  60. void ds3231_gettime(char* hour, char* min, char* sec)
  61. {
  62.         *sec = get_one_info(REG_SEC);
  63.         *min = get_one_info(REG_MIN);
  64.         *hour = get_one_info(REG_HOUR);
  65. }

  66. void ds3231_getdate(char* year, char* mon, char* day, char* weekday)
  67. {
  68.         if(weekday) *weekday = get_one_info(REG_DOW);
  69.         *day = get_one_info(REG_DATE);
  70.         *mon = get_one_info(REG_MON);
  71.         *year = get_one_info(REG_YEAR);       
  72. }

  73. void set_one_info(uchar addr, uchar setto)
  74. {
  75.         uchar temp;
  76.         //把十进制数据转换成BCD码
  77.         temp = setto / 10;
  78.         setto %= 10;
  79.         setto += temp * 16;
  80.         gpio_i2c_write(addr, setto);
  81. }

  82. void ds3231_settime(char hour, char min, char sec)
  83. {
  84.         if(sec!=DS3231_NOT_CHANGE) set_one_info(REG_SEC, sec);
  85.         if(min!=DS3231_NOT_CHANGE) set_one_info(REG_MIN, min);
  86.         if(hour!=DS3231_NOT_CHANGE) set_one_info(REG_HOUR, hour);
  87. }

  88. void ds3231_setdate(char year, char mon, char day)
  89. {
  90.         if(day!=DS3231_NOT_CHANGE) set_one_info(REG_DATE, day);
  91.         if(mon!=DS3231_NOT_CHANGE) set_one_info(REG_MON, mon);
  92.         if(year!=DS3231_NOT_CHANGE) set_one_info(REG_YEAR, year);       
  93. }

  94. code uchar dim[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
  95. ulong ds3231_getUnixTime()
  96. {
  97.         idata int dc;
  98.         idata char year, mon, date, hour, min, sec;
  99.         idata char i;
  100.        
  101.         ds3231_getdate(&year, &mon, &date, NULL);
  102.         ds3231_gettime(&hour, &min, &sec);
  103.        
  104.         dc = date;
  105.         for (i = 0; i<(mon-1); i++)
  106.                 dc += dim[i];
  107.         if ((mon > 2) && (((year) % 4) == 0))
  108.                 ++dc;
  109.         dc = dc + (365 * (year)) + (((year) + 3) / 4) - 1;

  110.         return ((((((dc * 24UL) + hour) * 60) + min) * 60) + sec) + SEC_1970_TO_2000;

  111. }

  112. void ds3231_init(void)
  113. {
  114.     //gpio_i2c_write(DEV_ADDR_DS3231, 0x0e, 0x1c);
  115. }

  116.        
复制代码


  1. //main.c

  2. #include "common.h"
  3. #include "uart_test.h"
  4. #include "i2c.h"
  5. #include "ds3231.h"

  6. void main()
  7. {
  8.         char h, m, s;
  9.        
  10.         common_init();

  11.         I2C_init();
  12.         ds3231_init();
  13.        
  14.         UartTest_Init();
  15.         UartTest_SendStr("system ok!\n");

  16.         ds3231_setdate(20, 3, 14);
  17.         ds3231_settime(21, 10, 33);

  18.         while(true)
  19.         {
  20.                 UartTest_SendStr("begin to get time...]");
  21.                 ds3231_getdate(&h, &m, &s, NULL);
  22.                 sprintf(uart_test_buf, "now: %04d-%02d-%02d ", (int)(h+2000), (int)m, (int)s);
  23.                 UartTest_SendStr(uart_test_buf);
  24.                 ds3231_gettime(&h, &m, &s);
  25.                 sprintf(uart_test_buf, "%02d:%02d:%02d\n", (int)h, (int)m, (int)s);
  26.                 UartTest_SendStr(uart_test_buf);
  27.                 delay(1000);
  28.         }
  29. }
复制代码
发表于 2020-3-15 10:54:19 | 显示全部楼层
STC8G能买了吗,官网直接下单?
发表于 2020-3-15 12:01:46 来自手机 | 显示全部楼层
先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。
 楼主| 发表于 2020-3-15 12:13:42 | 显示全部楼层
winfuture 发表于 2020-3-15 10:54
STC8G能买了吗,官网直接下单?

淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。
 楼主| 发表于 2020-3-15 12:15:03 | 显示全部楼层
wye11083 发表于 2020-3-15 12:01
先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。 ...

软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为什么硬件I2C读取到的全是FF。
发表于 2020-3-15 12:30:32 | 显示全部楼层
jinlei6394 发表于 2020-3-15 12:13
淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。 ...


STC8G能买了吗,官网直接下单?官网上买不到吗?
发表于 2020-3-15 13:28:13 来自手机 | 显示全部楼层
jinlei6394 发表于 2020-3-15 12:15
软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为 ...

那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转
 楼主| 发表于 2020-3-15 14:23:10 | 显示全部楼层
本帖最后由 jinlei6394 于 2020-3-15 14:39 编辑
fxhfxh 发表于 2020-3-15 12:30
STC8G能买了吗,官网直接下单?官网上买不到吗?


没去官方买,你可以试试。
淘宝上的什么STC官方店之类的一堆名字里带STC的店铺反正都有货。
 楼主| 发表于 2020-3-15 14:24:27 | 显示全部楼层
wye11083 发表于 2020-3-15 13:28
那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转 ...

也不能这么说啊。
如果是我代码有问题,那就学到点新知识。
要是芯片有问题,那不是正好让官方知道好去改么。
再说了,疫情期间,请响应国家号召,尽量不要出门。
发表于 2020-3-15 16:54:31 | 显示全部楼层
设置端口模试了没有
 楼主| 发表于 2020-3-15 22:10:50 | 显示全部楼层
本帖最后由 jinlei6394 于 2020-3-15 22:17 编辑
weavr 发表于 2020-3-15 16:54
设置端口模试了没有


怎么设置,什么端口?你是指输出引脚么?那个设置的是00啊,P14 P15
你看i2c.h的 I2C_init函数,设置的有什么问题吗?
发表于 2020-3-16 09:44:02 | 显示全部楼层
jinlei6394 发表于 2020-3-15 22:10
怎么设置,什么端口?你是指输出引脚么?那个设置的是00啊,P14 P15
你看i2c.h的 I2C_init函数,设置的有 ...

就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍
发表于 2020-3-16 12:11:38 来自手机 | 显示全部楼层
weavr 发表于 2020-3-16 09:44
就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍

对的,手册里提到这个说明。
发表于 2020-3-18 15:05:51 | 显示全部楼层
winfuture 发表于 2020-3-15 10:54
STC8G能买了吗,官网直接下单?

            STC8G部分系列已经在批量供货了:STC8G1K08-38I-TSSOP20/QFN20  STC8G2K64S4-35I-LQFP48/QFN48  另STC8H1K08-36I-TSSOP20\STC8H1K28-36I-LQFP32/QFN32也在批量供货中,需要可以加QQ送样测试:2593903262
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号-1 )

GMT+8, 2020-4-8 19:35

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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