[综合信息] 【HC32L136 demo板】+软件模拟I2C时序读写24C04

[复制链接]
142|2
 楼主 | 2019-9-30 20:21 | 显示全部楼层 |阅读模式
今晚搞了一下软件模拟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)
    {
                               
                               
    }
}

效果图:
ytt.jpg
可是发现一个问题,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

}

就可以了。
不明白为什么。
请大神指教,谢谢!

使用特权

评论回复
| 2019-9-30 23:35 | 显示全部楼层
楼主void InitSDAOutputH(void)和void InitSDAOutputL(void)是要初始化IO引脚并且初始化成高电平和低电平吗?
在上电后设置未输出的时候,需要先设置输出电平,再设置输出方向,这样才有初始化为指定的高电平或者低电平。
比如调用void InitSDAOutputL(void)之前,需要设置输出低:Gpio_ClrIO(GpioPortA, GpioPin12);或者Gpio_WriteOutputIO(GpioPortA, GpioPin12, FALSE);
pstcGpioCfg.enDrv; //这个设置驱动能力,是指引脚上的拉电流和灌电流的能力(强驱或者弱驱能力),不是指输出高低电平的意思。

使用特权

评论回复
| 2019-10-3 10:34 | 显示全部楼层
谢谢分享!

使用特权

评论回复
扫描二维码,随时随地手机跟帖
*滑动验证:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表