今晚搞了一下软件模拟I2C时序读写24C04,终于成功了。
代码:
#include "gpio.h"
/******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
#define uchar unsigned char
#define uint unsigned int
/******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
stc_gpio_config_t pstcGpioCfg;
/******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/******************************************************************************
* Local variable definitions ('static') *
******************************************************************************/
/******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
#define SDA_0 Gpio_ClrIO(GpioPortA, GpioPin12)
#define SDA_1 Gpio_SetIO(GpioPortA, GpioPin12)
#define SCL_0 Gpio_ClrIO(GpioPortA, GpioPin11)
#define SCL_1 Gpio_SetIO(GpioPortA, GpioPin11)
#define SDA Gpio_GetInputIO(GpioPortA, GpioPin12)
/*****************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
unsigned char buffer[3];
/****************************************************************************
* 名 称: DelayMS()
* 功 能: 以毫秒为单位延时,系统时钟不配置时默认为16M(用示波器测量相当精确)
* 入口参数: msec 延时参数,值越大,延时越久
* 出口参数: 无
****************************************************************************/
void DelayMS(uint msec)
{
uint i,j;
for (i=0; i<msec; i++)
for (j=0; j<535; j++);
}
void InitSDAInput(void)
{
///< 端口方向配置->输入
pstcGpioCfg.enDir = GpioDirIn;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvH;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出关闭
pstcGpioCfg.enOD = GpioOdDisable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg);
}
void InitSDAOutputH(void)
{
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvH;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg); //SDA
}
void InitSDAOutputL(void)
{
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvL;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg); //SDA
}
//-----------------------------------------------------------------------------------------
//函数名称:Delay()
//功 能:延时子程序
//-----------------------------------------------------------------------------------------
void Delay(unsigned char us) //5,7,9
{
char i;
while(--us)
{
for(i=0;i<25;i++);
}
}
//-----------------------------------------------------------------------------------------
//函数名称:Delayms()
//-----------------------------------------------------------------------------------------
void Delayms(unsigned int ims)
{
unsigned int i,j;
for(i=0;i<ims;i++)
for(j=0;j<265;j++) { Delay(1); }
}
void Start()
{
SCL_0;
InitSDAOutputH();
SDA_1;
Delay(5);
SCL_1;
Delay(5);
InitSDAOutputL();
SDA_0;
Delay(5);
SCL_0;
Delay(5);
}
void Stop()
{
SCL_0;
InitSDAOutputL();
SDA_0;
Delay(5);
SCL_1;
Delay(5);
InitSDAOutputH();
SDA_1;
Delay(5);
}
char ACK ()
{
char c,i=0;
InitSDAOutputH();
SDA_1;
Delay(5);
SCL_0;
Delay(5);
SCL_1;
Delay(5);
InitSDAInput();
Delay(5);
// if(SDA==1)
// c=1;
// else
// c=0;
while(SDA==1)
{
i++;
if(i>100)
break;
}
// InitSDAOutput();
Delay(5);
SCL_0;
return c;
}
void NOACK()//·ÇÓ¦´ðÐźÅ
{
InitSDAOutputH();
SDA_1;
SCL_0;
Delay(5);
SCL_1;
Delay(5);
SCL_0;
Delay(5);
}
void SendChar(unsigned char ch)
{
unsigned char i;
i=8;
do
{
if(ch&0x80)
{
InitSDAOutputH();
SDA_1;
}
else
{
InitSDAOutputL();
SDA_0;
}
Delay(5);
SCL_1;
Delay(5);
SCL_0;
Delay(5);
ch<<=1;
}while(--i!=0);
}
unsigned char RecChar()
{
unsigned char i,j;
i=8;
j=0;
InitSDAInput();
do
{
SCL_1;
Delay(5);
j=(j<<1);
if(SDA==1)
j=j|1;
Delay(5);
SCL_0;
Delay(5);
}while(--i!=0);
return j;
}
void WriteChar(unsigned int addr,unsigned char ch)
{
unsigned char c;
c=((*((unsigned char *)&addr))<<1)&0x02;
Start();
SendChar(0xa0|c);
ACK();
SendChar(addr);
ACK();
SendChar(ch);
ACK();
Stop();
for(ch=0xff;ch!=0;ch--) ;
}
unsigned char ReadChar(unsigned int addr)
{
unsigned char ch;
ch=((*((unsigned char *)&addr))<<1)&0x02;
Start();
SendChar(0xa0|ch);
ACK();
SendChar(addr);
ACK();
Start();
SendChar(0xa1|ch);
ACK();
ch=RecChar();
NOACK();
Stop();
return ch;
}
/**
******************************************************************************
** \brief Main function of project
**
** \return uint32_t return value, if needed
**
** This sample
**
******************************************************************************/
int32_t main(void)
{
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvH;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
//Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg); //SDA
Gpio_Init(GpioPortA, GpioPin11, &pstcGpioCfg); //SCL
//InitSDAOutput();
buffer[0]=ReadChar(0);
Delay(100); //延时一段时间
WriteChar(0,0x55);
Delayms(20);
WriteChar(1,0xaa);
Delayms(20);
WriteChar(2,0x27);
Delayms(20);
buffer[0]=ReadChar(1);
buffer[1]=ReadChar(2);
buffer[2]=ReadChar(0);
while(1)
{
}
}
效果图:
可是发现一个问题,PA12不好拉低,而PA11就可以。
PA11初始化:
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvH;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin11, &pstcGpioCfg); //SCL
这样可以正常拉高拉低。
可是PA12则不行。
我搞了一下,找了个不太好的办法。
拉高之前这么初始化:
void InitSDAOutputH(void)
{
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
pstcGpioCfg.enDrv = GpioDrvH;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg); //SDA
}
拉低之前这么初始化:
void InitSDAOutputL(void)
{
///< 端口方向配置->输出
pstcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->低驱动能力
pstcGpioCfg.enDrv = GpioDrvL;
///< 端口上下拉配置->无上下拉
pstcGpioCfg.enPuPd = GpioNoPuPd;
///< 端口开漏输出配置->开漏输出使能
pstcGpioCfg.enOD = GpioOdEnable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
pstcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(GpioPortA, GpioPin12, &pstcGpioCfg); //SDA
}
就可以了。
不明白为什么。
请大神指教,谢谢!
|
@Cjy_JDxy :我把函数改了改,传参数加了地址,数组,长度,发现读取数据是正常的,用你的例程发现第一组数据总是ff
@xw10221102 :没有
你好,想问一下楼主这个例程buffer[0]读数据的时候遇到一直是0xff的情况吗
这个SCL不配置吗,我用的你的例子,加上SCL收发也不正常