stc8G1k-sop8封装I2C功能怪怪问题请教
本帖最后由 zhang_yg188 于 2023-8-21 15:21 编辑以前用STC8H-tssop20的MCU,功能已经OK,就是STC的P32和P33口作为I2C从机,接受上位机指令,P10点亮8个WS2812。现在准备换STC8G的SOP8封装,只是更改了驱动2812的管脚定义,发现不能亮灯,上位机也扫描不到STC的I2C,IO和I2C的设置都是用的官网上的库函数。焊接了一个试验板,P54连接一个普通LED的负极加电阻,试验闪灯功能,发现只要I2C用I2C_P14_P15,功能OK ,用I2C_P24_P25和 I2C_P33_P32,不能闪灯。请教下是什么问题,程序如下:
////*************主程序
#include "config.h"
#include "GPIO.h"
#include "timer.h"
#include "I2C.h"
#include "delay.h"
#include<all.h>
/************* 本地变量声明 **************/
u8 from_maser_data = 0x01; //从i2c主机得到的命令符,
u8 to_maser_data; //返回给主机的按键的电平
u8 dt=100;
u8 time_counter=0;
u8 delay_each = 5000 ,delay_cy=8;
/******************** IO口配置 ********************/
void GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P1,&GPIO_InitStructure); //P1口初始化,预备接8个LED,设置成准双向标准接口。
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //P3口初始化,设置成准双向标准接口,作为I2C和触摸按键接口。
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P5,&GPIO_InitStructure); //P5口初始化,设置成准双向标准接口,作为I2C和触摸按键接口。
}
/************************ 定时器配置 ****************************/
void Timer_config(void)
{
TIM_InitTypeDef TIM_InitStructure; //结构定义
TIM_InitStructure.TIM_Interrupt = ENABLE; //中断是否允许, ENABLE或DISABLE. (注意: Timer2固定为16位自动重装, 中断固定为低优先级)
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 1000); //初值
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer2,&TIM_InitStructure); //初始化Timer2 Timer0,Timer1,Timer2,Timer3,Timer4 1毫秒/次
}
/****************I2C初始化函数 *****************/
void I2C_config(void)
{
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_Slave; //从机 //主从选择 I2C_Mode_Master, I2C_Mode_Slave
I2C_InitStructure.I2C_Enable = ENABLE; //I2C功能使能, ENABLE, DISABLE
I2C_InitStructure.I2C_SL_ESTAI= ENABLE; //从机接收START信号中断使能,ENABLE, DISABLE
I2C_InitStructure.I2C_SL_ERXI = ENABLE; //从机接收1字节数据中断使能,ENABLE, DISABLE
I2C_InitStructure.I2C_SL_ETXI = ENABLE; //从机发送1字节数据中断使能,ENABLE, DISABLE
I2C_InitStructure.I2C_SL_ESTOI= ENABLE; //从机接收STOP信号中断使能, ENABLE, DISABLE
I2C_InitStructure.I2C_SL_MA = ENABLE; //使能从机地址比较功能, ENABLE, DISABLE
I2C_InitStructure.I2C_SL_ADR = 94; //从机地址
//I2C_InitStructure.I2C_IoUse = I2C_P14_P15; //用P14和P15,LED闪烁功能OK
//I2C_InitStructure.I2C_IoUse = I2C_P24_P25; //用P24和P25,LED不闪烁
I2C_InitStructure.I2C_IoUse = I2C_P33_P32; //用P32和P33,LED也不闪烁// IO口切换 I2C_P14_P15, I2C_P24_P25, I2C_P33_P32,接口为:P33(SDA),P32(SCL)
I2C_Init(&I2C_InitStructure);
}
void main(void)
{
u8 dt=500;
GPIO_config();
Timer_config();
//I2C_config(); //注释这句,闪灯OK;如果打开注释,I2C_InitStructure.I2C_IoUse = I2C_P14_P15; 闪灯OK,其余两个不闪烁。
EA = 1;
while(1){
P54 =1;
delay_ms(dt);
P54 = 0;
delay_ms(dt);
}
}
/****************I2C库函数 *****************/
#include "I2C.h"
//#define Software_I2C //使能软件模拟I2C;不用SOFTI2C
u8 I2C_BUF_type I2C_Buffer;
I2C_IsrTypeDef I2CIsr;
//extern bit DisplayFlag;
extern u8 from_maser_data; //从i2c主机得到的命令符,
extern u8 to_maser_data; //返回给主机的触摸按键的电平
//========================================================================
// 函数: void I2C_Init(I2C_InitTypeDef *I2Cx)
// 描述: I2C初始化程序.
// 参数: I2Cx: 结构参数,请参考I2C.h里的定义.
// 返回: none.
// 版本: V1.0, 2020-09-16
//========================================================================
void I2C_Init(I2C_InitTypeDef *I2Cx)
{
EAXSFR(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展SFR(XSFR) */
if(I2Cx->I2C_Mode == I2C_Mode_Master)
{
I2C_Master(); //设为主机
I2CMSST = 0x00; //清除I2C主机状态寄存器
I2C_Master_Inturrupt(I2Cx->I2C_MS_Interrupt);
I2C_SetSpeed(I2Cx->I2C_Speed);
if(I2Cx->I2C_MS_WDTA == ENABLE) I2C_WDTA_EN(); //使能自动发送
else I2C_WDTA_DIS(); //禁止自动发送
}
else
{
I2C_Slave(); //设为从机
I2CSLST = 0x00; //清除I2C从机状态寄存器
if(I2Cx->I2C_SL_ESTAI == ENABLE) I2C_ESTAI_EN(); //使能从机接收START信号中断
else I2C_ESTAI_DIS(); //禁止从机接收START信号中断
if(I2Cx->I2C_SL_ERXI == ENABLE) I2C_ERXI_EN(); //使能从机接收1字节数据中断
else I2C_ERXI_DIS(); //禁止从机接收1字节数据中断
if(I2Cx->I2C_SL_ETXI == ENABLE) I2C_ETXI_EN(); //使能从机发送1字节数据中断
else I2C_ETXI_DIS(); //禁止从机发送1字节数据中断
if(I2Cx->I2C_SL_ESTOI == ENABLE) I2C_ESTOI_EN(); //使能从机接收STOP信号中断
else I2C_ESTOI_DIS(); //禁止从机接收STOP信号中断
I2C_Address(I2Cx->I2C_SL_ADR);
if(I2Cx->I2C_SL_MA == ENABLE) I2C_MATCH_EN(); //从机地址比较功能,只接受相匹配地址
else I2C_MATCH_DIS(); //禁止从机地址比较功能,接受所有设备地址
}
P_SW2 = (P_SW2 & ~(3<<4)) | I2Cx->I2C_IoUse;
I2C_Function(I2Cx->I2C_Enable);
I2CIsr.isda = 1;
I2CIsr.isma = 1;
I2CIsr.addr = 0;
I2CTXD = I2C_Buffer;
EAXRAM(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展RAM(XRAM) */
}
#ifdef Software_I2C
#define SLAW 0x5A
#define SLAR 0x5B
sbit SDA = P0^1; //定义SDA
sbit SCL = P0^0; //定义SCL
/****************************/
void I2C_Delay(void) //for normal MCS51, delay (2 * dly + 4) T, for STC12Cxxxx delay (4 * dly + 10) T
{
u8dly;
dly = MAIN_Fosc / 2000000UL; //按2us计算
while(--dly);
}
/****************************/
void I2C_Start(void) //start the I2C, SDA High-to-low when SCL is high
{
SDA = 1;
I2C_Delay();
SCL = 1;
I2C_Delay();
SDA = 0;
I2C_Delay();
SCL = 0;
I2C_Delay();
}
void I2C_Stop(void) //STOP the I2C, SDA Low-to-high when SCL is high
{
SDA = 0;
I2C_Delay();
SCL = 1;
I2C_Delay();
SDA = 1;
I2C_Delay();
}
void S_ACK(void) //Send ACK (LOW)
{
SDA = 0;
I2C_Delay();
SCL = 1;
I2C_Delay();
SCL = 0;
I2C_Delay();
}
void S_NoACK(void) //Send No ACK (High)
{
SDA = 1;
I2C_Delay();
SCL = 1;
I2C_Delay();
SCL = 0;
I2C_Delay();
}
void I2C_Check_ACK(void) //Check ACK, If F0=0, then right, if F0=1, then error
{
SDA = 1;
I2C_Delay();
SCL = 1;
I2C_Delay();
F0= SDA;
SCL = 0;
I2C_Delay();
}
/****************************/
void I2C_WriteAbyte(u8 dat) //write a byte to I2C
{
u8 i;
i = 8;
do
{
if(dat & 0x80)SDA = 1;
else SDA = 0;
dat <<= 1;
I2C_Delay();
SCL = 1;
I2C_Delay();
SCL = 0;
I2C_Delay();
}
while(--i);
}
/****************************/
u8 I2C_ReadAbyte(void) //read A byte from I2C
{
u8 i,dat;
i = 8;
SDA = 1;
do
{
SCL = 1;
I2C_Delay();
dat <<= 1;
if(SDA) dat++;
SCL= 0;
I2C_Delay();
}
while(--i);
return(dat);
}
/****************************/
void WriteNbyte(u8 addr, u8 *p, u8 number) /*WordAddress,First Data Address,Byte lenth */
{
I2C_Start();
I2C_WriteAbyte(SLAW);
I2C_Check_ACK();
if(!F0) //F0=0,right, F0=1,error
{
I2C_WriteAbyte(addr);
I2C_Check_ACK();
if(!F0)
{
do
{
I2C_WriteAbyte(*p); p++;
I2C_Check_ACK();
if(F0)break;
}
while(--number);
}
}
I2C_Stop();
}
/****************************/
void ReadNbyte(u8 addr, u8 *p, u8 number) /*WordAddress,First Data Address,Byte lenth */
{
I2C_Start();
I2C_WriteAbyte(SLAW);
I2C_Check_ACK();
if(!F0)
{
I2C_WriteAbyte(addr);
I2C_Check_ACK();
if(!F0)
{
I2C_Start();
I2C_WriteAbyte(SLAR);
I2C_Check_ACK();
if(!F0)
{
do
{
*p = I2C_ReadAbyte(); p++;
if(number != 1) S_ACK(); //send ACK
}
while(--number);
S_NoACK(); //send no ACK
}
}
}
I2C_Stop();
}
#else
#define SLAW 0xA2
#define SLAR 0xA3
//========================================================================
// 函数: void Wait (void)
// 描述: 等待主机模式I2C控制器执行完成I2CMSCR.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void Wait()
{
while (!(I2CMSST & 0x40));
I2CMSST &= ~0x40;
}
//========================================================================
// 函数: void Start (void)
// 描述: I2C总线起始函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void Start()
{
I2CMSCR = 0x01; //发送START命令
Wait();
}
//========================================================================
// 函数: void SendData (char dat)
// 描述: I2C发送一个字节数据函数.
// 参数: 发送的数据.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendData(char dat)
{
I2CTXD = dat; //写数据到数据缓冲区
I2CMSCR = 0x02; //发送SEND命令
Wait();
}
//========================================================================
// 函数: void RecvACK (void)
// 描述: I2C获取ACK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void RecvACK()
{
I2CMSCR = 0x03; //发送读ACK命令
Wait();
}
//========================================================================
// 函数: char RecvData (void)
// 描述: I2C读取一个字节数据函数.
// 参数: none.
// 返回: 读取数据.
// 版本: V1.0, 2020-09-15
//========================================================================
char RecvData()
{
I2CMSCR = 0x04; //发送RECV命令
Wait();
return I2CRXD;
}
//========================================================================
// 函数: void SendACK (void)
// 描述: I2C发送ACK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendACK()
{
I2CMSST = 0x00; //设置ACK信号
I2CMSCR = 0x05; //发送ACK命令
Wait();
}
//========================================================================
// 函数: void SendNAK (void)
// 描述: I2C发送NAK函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void SendNAK()
{
I2CMSST = 0x01; //设置NAK信号
I2CMSCR = 0x05; //发送ACK命令
Wait();
}
//========================================================================
// 函数: void Stop (void)
// 描述: I2C总线停止函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void Stop()
{
I2CMSCR = 0x06; //发送STOP命令
Wait();
}
//========================================================================
// 函数: void WriteNbyte(u8 addr, u8 *p, u8 number)
// 描述: I2C写入数据函数.
// 参数: addr: 指定地址, *p写入数据存储位置, number写入数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void WriteNbyte(u8 addr, u8 *p, u8 number)/*WordAddress,First Data Address,Byte lenth */
{
EAXSFR(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展SFR(XSFR) */
Start(); //发送起始命令
SendData(SLAW); //发送设备地址+写命令
RecvACK();
SendData(addr); //发送存储地址
RecvACK();
do
{
SendData(*p++);
RecvACK();
}
while(--number);
Stop(); //发送停止命令
EAXRAM(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展RAM(XRAM) */
}
//========================================================================
// 函数: void ReadNbyte(u8 addr, u8 *p, u8 number)
// 描述: I2C读取数据函数.
// 参数: addr: 指定地址, *p读取数据存储位置, number读取数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void ReadNbyte(u8 addr, u8 *p, u8 number) /*WordAddress,First Data Address,Byte lenth */
{
EAXSFR(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展SFR(XSFR) */
Start(); //发送起始命令
SendData(SLAW); //发送设备地址+写命令
RecvACK();
SendData(addr); //发送存储地址
RecvACK();
Start(); //发送起始命令
SendData(SLAR); //发送设备地址+读命令
RecvACK();
do
{
*p = RecvData();
p++;
if(number != 1) SendACK(); //send ACK
}
while(--number);
SendNAK(); //send no ACK
Stop(); //发送停止命令
EAXRAM(); /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展RAM(XRAM) */
}
#endif
//========================================================================
// 函数: void I2C_Isr (void) interrupt I2C_VECTOR
// 描述: I2C中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_Isr() interrupt I2C_VECTOR
{
char store;
store = P_SW2;
P_SW2 |= 0x80;
if (I2CSLST & 0x40)
{
I2CSLST &= ~0x40; //处理START事件
}
else if (I2CSLST & 0x20)
{
I2CSLST &= ~0x20; //处理RECV事件,SLACKO设置为0
if (I2CIsr.isda)
{
I2CIsr.isda = 0; //处理RECV事件(RECV DEVICE ADDR)
}
else if (I2CIsr.isma)
{
I2CIsr.isma = 0; //处理RECV事件(RECV MEMORY ADDR)
I2CIsr.addr = I2CRXD;
I2CTXD = I2C_Buffer;
}
else
{
I2C_Buffer = I2CRXD; //处理RECV事件(RECV DATA)
from_maser_data = I2CRXD;
}
}
else if (I2CSLST & 0x10)
{
I2CSLST &= ~0x10; //处理SEND事件
if (I2CSLST & 0x02)
{
//I2CTXD = 0xff;
I2CTXD =to_maser_data; // 0x88;; //0x88;
}
else
{
I2CTXD = I2C_Buffer[++I2CIsr.addr];
}
}
else if (I2CSLST & 0x08)
{
I2CSLST &= ~0x08; //处理STOP事件
I2CIsr.isda = 1;
I2CIsr.isma = 1;
// DisplayFlag = 1;
}
P_SW2 = store;
}
下载是,已经勾选了“复位脚用作IO”。 用I2C_P24_P25和 I2C_P33_P32时,P2.4,P2.5 / P3.3,P3.2的IO口模式初始化了没有? 本帖最后由 zhang_yg188 于 2023-8-22 09:00 编辑
void GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P1,&GPIO_InitStructure); //P1口初始化,预备接8个LED,设置成准双向标准接口。
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P2,&GPIO_InitStructure); //P2口初始化,设置成准双向标准接口,作为I2C和触摸按键接口。
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //P3口初始化,设置成准双向标准接口,作为I2C和触摸按键接口。
GPIO_InitStructure.Pin= GPIO_Pin_All; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P5,&GPIO_InitStructure); //P5口初始化
}
P1,P2,P3,P5初始化了,还是一样。本身SOP8脚的只有P3和P5口有引脚。 现在只是想用P3口设置为I2C,P5口作为普通输入、输出,但是P5口不受控制。
用仿真功能去发现错在哪,不要猜
用 STC-USB Link1D 仿真 STC8 系列 MCU - 编译器/仿真器/ISP下载/做自己的ISP - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
#define I2C_P33_P32 0 //STC8G1K08-8pin系列 ,STC8G1K08A-8pin系列
修改这个gpio的配置 最帅不过阿良 发表于 2023-12-20 15:04
#define I2C_P33_P32 0 //STC8G1K08-8pin系列 ,STC8G1K08A-8pin系列
修改这个gpio的配置 ...
看到这个,真的很关键,还好看到这个贴子,谢谢博主,真实有效!!
页:
[1]