jinlei6394 发表于 2020-3-15 01:42:07

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

本帖最后由 jinlei6394 于 2020-3-16 01:35 编辑

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



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

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

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

    I2CMSST = 0x00;
}


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


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

时钟频率:30MHZ


// i2c.c

#include "common.h"
#include "i2c.h"

#define SCL P15
#define SDA P14

void Wait()
{
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

void I2C_init()
{
    //I2C 打开EAXFR
    P_SW2 |= 0x80;
    //P_SW2 = SET_BIT_1(P_SW2, 7);
       
    //I2C 使用第一组(00)引脚
    P_SW2 &= ~B00110000; //#define B00110000 0x30
    //P_SW2 = SET_BIT_0(P_SW2, 4);
    //P_SW2 = SET_BIT_0(P_SW2, 5);

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

    I2CMSST = 0x00;
}

/*******I2C总线启动函数*************/
void I2C_Start()
{
    I2CMSCR = 0x01;                           //发送START命令
    Wait();
}

/*******I2C总线停止函数*************/
void I2C_Stop()
{
    I2CMSCR = 0x06;                           //发送STOP命令
    Wait();
}

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

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

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

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

/*********I2C总线单字节读函数*************/
char I2C_RecvByte()
{
    I2CMSCR = 0x04;                           //发送RECV命令
    Wait();
    return I2CRXD;
}

void I2C_RecvBytes(char* buf, int write_n)
{
        for( ; write_n>0; write_n--)
        {
                *buf=I2C_RecvByte();       //开始逐个读出字节
                buf++;
                if(write_n>1)
                        I2C_Send_ACK();                       //应答
                else
                        I2C_Send_NAK();             //总线非应答
        }
}

void I2C_SendBytes(char* buf, int write_n)
{
        for( ; write_n>0; write_n--)
        {
                I2C_SendByte(*buf);       //开始逐个读出字节
                buf++;
                I2C_Recv_ACK();
                //if(F0)
                //        break;
        }
}



//ds3231.c

#include "common.h"
#include "i2c.h"
#include "ds3231.h"
#include "uart_test.h"

#define DS3231_WriteAddress 0xD0    //器件写地址
#define DS3231_ReadAddress0xD1    //器件读地址

#define REG_SEC                0x00
#define REG_MIN                0x01
#define REG_HOUR        0x02
#define REG_DOW                0x03
#define REG_DATE        0x04
#define REG_MON                0x05
#define REG_YEAR        0x06
#define REG_CON                0x0e
#define REG_STATUS        0x0f
#define REG_AGING        0x10
#define REG_TEMPM        0x11
#define REG_TEMPL        0x12

#define SEC_1970_TO_2000 946684800

void gpio_i2c_write(uchar addr, uchar dat)
{
        I2C_Start();
        I2C_SendByte(DS3231_WriteAddress);
        I2C_Recv_ACK();
        I2C_SendByte(addr);
        I2C_Recv_ACK();
        I2C_SendByte(dat);
        I2C_Recv_ACK();
        I2C_Stop();
}

uchar gpio_i2c_read(uchar addr)
{
    uchar dat;
       
        I2C_Start();
        I2C_SendByte(DS3231_WriteAddress);
        I2C_Recv_ACK();
        I2C_SendByte(addr);
        I2C_Recv_ACK();
       
        I2C_Start();
        I2C_SendByte(DS3231_ReadAddress);
        I2C_Recv_ACK();
        dat = I2C_RecvByte();//就这个dat,读出来的永远是0xFF
        I2C_Send_NAK();
        I2C_Stop();
        return dat;
}

char get_one_info(uchar addr)
{
        uchar r, temp;
        r = gpio_i2c_read(addr);
        //把BCD码转换成十进制数据
        temp = r / 16;
        r %= 16;
        r += temp * 10;
        return r;
}

void ds3231_gettime(char* hour, char* min, char* sec)
{
        *sec = get_one_info(REG_SEC);
        *min = get_one_info(REG_MIN);
        *hour = get_one_info(REG_HOUR);
}

void ds3231_getdate(char* year, char* mon, char* day, char* weekday)
{
        if(weekday) *weekday = get_one_info(REG_DOW);
        *day = get_one_info(REG_DATE);
        *mon = get_one_info(REG_MON);
        *year = get_one_info(REG_YEAR);       
}

void set_one_info(uchar addr, uchar setto)
{
        uchar temp;
        //把十进制数据转换成BCD码
        temp = setto / 10;
        setto %= 10;
        setto += temp * 16;
        gpio_i2c_write(addr, setto);
}

void ds3231_settime(char hour, char min, char sec)
{
        if(sec!=DS3231_NOT_CHANGE) set_one_info(REG_SEC, sec);
        if(min!=DS3231_NOT_CHANGE) set_one_info(REG_MIN, min);
        if(hour!=DS3231_NOT_CHANGE) set_one_info(REG_HOUR, hour);
}

void ds3231_setdate(char year, char mon, char day)
{
        if(day!=DS3231_NOT_CHANGE) set_one_info(REG_DATE, day);
        if(mon!=DS3231_NOT_CHANGE) set_one_info(REG_MON, mon);
        if(year!=DS3231_NOT_CHANGE) set_one_info(REG_YEAR, year);       
}

code uchar dim[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
ulong ds3231_getUnixTime()
{
        idata int dc;
        idata char year, mon, date, hour, min, sec;
        idata char i;
       
        ds3231_getdate(&year, &mon, &date, NULL);
        ds3231_gettime(&hour, &min, &sec);
       
        dc = date;
        for (i = 0; i<(mon-1); i++)
                dc += dim;
        if ((mon > 2) && (((year) % 4) == 0))
                ++dc;
        dc = dc + (365 * (year)) + (((year) + 3) / 4) - 1;

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

}

void ds3231_init(void)
{
    //gpio_i2c_write(DEV_ADDR_DS3231, 0x0e, 0x1c);
}

       


//main.c

#include "common.h"
#include "uart_test.h"
#include "i2c.h"
#include "ds3231.h"

void main()
{
        char h, m, s;
       
        common_init();

        I2C_init();
        ds3231_init();
       
        UartTest_Init();
        UartTest_SendStr("system ok!\n");

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

        while(true)
        {
                UartTest_SendStr("begin to get time...]");
                ds3231_getdate(&h, &m, &s, NULL);
                sprintf(uart_test_buf, "now: %04d-%02d-%02d ", (int)(h+2000), (int)m, (int)s);
                UartTest_SendStr(uart_test_buf);
                ds3231_gettime(&h, &m, &s);
                sprintf(uart_test_buf, "%02d:%02d:%02d\n", (int)h, (int)m, (int)s);
                UartTest_SendStr(uart_test_buf);
                delay(1000);
        }
}

winfuture 发表于 2020-3-15 10:54:19

STC8G能买了吗,官网直接下单?

wye11083 发表于 2020-3-15 12:01:46

先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。

jinlei6394 发表于 2020-3-15 12:13:42

winfuture 发表于 2020-3-15 10:54
STC8G能买了吗,官网直接下单?

淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。

jinlei6394 发表于 2020-3-15 12:15:03

wye11083 发表于 2020-3-15 12:01
先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。 ...

软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为什么硬件I2C读取到的全是FF。

fxhfxh 发表于 2020-3-15 12:30:32

jinlei6394 发表于 2020-3-15 12:13
淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。 ...


STC8G能买了吗,官网直接下单?官网上买不到吗?

wye11083 发表于 2020-3-15 13:28:13

jinlei6394 发表于 2020-3-15 12:15
软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为 ...

那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转

jinlei6394 发表于 2020-3-15 14:23:10

本帖最后由 jinlei6394 于 2020-3-15 14:39 编辑

fxhfxh 发表于 2020-3-15 12:30
STC8G能买了吗,官网直接下单?官网上买不到吗?

没去官方买,你可以试试。
淘宝上的什么STC官方店之类的一堆名字里带STC的店铺反正都有货。

jinlei6394 发表于 2020-3-15 14:24:27

wye11083 发表于 2020-3-15 13:28
那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转 ...

也不能这么说啊。
如果是我代码有问题,那就学到点新知识。
要是芯片有问题,那不是正好让官方知道好去改么。
再说了,疫情期间,请响应国家号召,尽量不要出门。

weavr 发表于 2020-3-15 16:54:31

设置端口模试了没有

jinlei6394 发表于 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函数,设置的有什么问题吗?

weavr 发表于 2020-3-16 09:44:02

jinlei6394 发表于 2020-3-15 22:10
怎么设置,什么端口?你是指输出引脚么?那个设置的是00啊,P14 P15
你看i2c.h的 I2C_init函数,设置的有 ...

就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍

ZJetWay 发表于 2020-3-16 12:11:38

weavr 发表于 2020-3-16 09:44
就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍

对的,手册里提到这个说明。

monarchess 发表于 2020-3-18 15:05:51

winfuture 发表于 2020-3-15 10:54
STC8G能买了吗,官网直接下单?

            STC8G部分系列已经在批量供货了:STC8G1K08-38I-TSSOP20/QFN20STC8G2K64S4-35I-LQFP48/QFN48另STC8H1K08-36I-TSSOP20\STC8H1K28-36I-LQFP32/QFN32也在批量供货中,需要可以加QQ送样测试:2593903262
页: [1]
查看完整版本: STC8G1K12-20pin,硬件I2C读取数据总是FF,请帮我看看哪有错误?