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);
}
}
STC8G能买了吗,官网直接下单? 先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。 winfuture 发表于 2020-3-15 10:54
STC8G能买了吗,官网直接下单?
淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。 wye11083 发表于 2020-3-15 12:01
先查你有没有收到ack吧。0是ack,1是nack,但是你要确认硬件寄存器的值。另外可以考虑软件模拟。 ...
软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为什么硬件I2C读取到的全是FF。 jinlei6394 发表于 2020-3-15 12:13
淘宝就有的卖啊,2块钱一个。
已经有人在卖基于STC8G1K12-20PIN做的最小系统开发板了。 ...
STC8G能买了吗,官网直接下单?官网上买不到吗? jinlei6394 发表于 2020-3-15 12:15
软件模拟功能完全正常,DS3231和SHT30都能正常读取数据。
所以电路、器件应该是没问题的。
就是不知道为 ...
那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转 本帖最后由 jinlei6394 于 2020-3-15 14:39 编辑
fxhfxh 发表于 2020-3-15 12:30
STC8G能买了吗,官网直接下单?官网上买不到吗?
没去官方买,你可以试试。
淘宝上的什么STC官方店之类的一堆名字里带STC的店铺反正都有货。 wye11083 发表于 2020-3-15 13:28
那你还折腾它干个毛线,时间就是金钱就是生命,折腾硬件外设还不如出去转转 ...
也不能这么说啊。
如果是我代码有问题,那就学到点新知识。
要是芯片有问题,那不是正好让官方知道好去改么。
再说了,疫情期间,请响应国家号召,尽量不要出门。 设置端口模试了没有 本帖最后由 jinlei6394 于 2020-3-15 22:17 编辑
weavr 发表于 2020-3-15 16:54
设置端口模试了没有
怎么设置,什么端口?你是指输出引脚么?那个设置的是00啊,P14 P15
你看i2c.h的 I2C_init函数,设置的有什么问题吗? jinlei6394 发表于 2020-3-15 22:10
怎么设置,什么端口?你是指输出引脚么?那个设置的是00啊,P14 P15
你看i2c.h的 I2C_init函数,设置的有 ...
就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍 weavr 发表于 2020-3-16 09:44
就是标准、推挽、开漏等这些设置,STC最好上电都设置一遍
对的,手册里提到这个说明。 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]