打印
[综合信息]

【HC32L136 demo板】+软件模拟I2C时序读写24C04

[复制链接]
4916|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今晚搞了一下软件模拟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

}

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

使用特权

评论回复
评论
xw10221102 2020-1-8 17:29 回复TA
@Cjy_JDxy :我把函数改了改,传参数加了地址,数组,长度,发现读取数据是正常的,用你的例程发现第一组数据总是ff 
Cjy_JDxy 2020-1-8 17:20 回复TA
@xw10221102 :没有 
xw10221102 2020-1-8 16:41 回复TA
你好,想问一下楼主这个例程buffer[0]读数据的时候遇到一直是0xff的情况吗 
xw10221102 2019-12-27 17:31 回复TA
这个SCL不配置吗,我用的你的例子,加上SCL收发也不正常 
沙发
martinhu| | 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; //这个设置驱动能力,是指引脚上的拉电流和灌电流的能力(强驱或者弱驱能力),不是指输出高低电平的意思。

使用特权

评论回复
板凳
zlmin| | 2019-10-3 10:34 | 只看该作者
谢谢分享!

使用特权

评论回复
地板
Cjy_JDxy|  楼主 | 2019-12-27 18:06 | 只看该作者
Gpio_Init(GpioPortA, GpioPin11, &pstcGpioCfg);                        //SCL
配置了呀

使用特权

评论回复
5
Cjy_JDxy|  楼主 | 2019-12-28 15:07 | 只看该作者
martinhu 发表于 2019-9-30 23:35
楼主void InitSDAOutputH(void)和void InitSDAOutputL(void)是要初始化IO引脚并且初始化成高电平和低电平吗 ...

那两个函数一个是输出高之前调用,一个是输出低之前调用,你没仔细看我的代码吧

使用特权

评论回复
6
Cjy_JDxy|  楼主 | 2020-1-8 18:07 | 只看该作者
第一次读,如果没写过,那就是0xff啊

使用特权

评论回复
7
updownq| | 2020-1-10 20:47 | 只看该作者
           

使用特权

评论回复
8
wengh2016| | 2020-1-10 20:47 | 只看该作者
谢谢分享的。         

使用特权

评论回复
9
qiufengsd| | 2020-1-10 20:48 | 只看该作者
没有硬件iic吗  

使用特权

评论回复
10
kmzuaz| | 2020-1-10 20:48 | 只看该作者
楼主自己开发的iic吗?   

使用特权

评论回复
11
plsbackup| | 2020-1-10 20:48 | 只看该作者
看着好复杂了。            

使用特权

评论回复
12
Cjy_JDxy|  楼主 | 2020-1-11 07:59 | 只看该作者

有。

使用特权

评论回复
13
Cjy_JDxy|  楼主 | 2020-1-11 08:00 | 只看该作者
kmzuaz 发表于 2020-1-10 20:48
楼主自己开发的iic吗?

模拟时序呀

使用特权

评论回复
14
nvjwiciw659| | 2020-4-21 18:24 | 只看该作者
多谢分享,很有用

使用特权

评论回复
15
米多0036| | 2020-4-22 22:39 | 只看该作者
就是0xff啊

使用特权

评论回复
16
18255236907| | 2021-12-9 12:35 | 只看该作者
不是都是封装库函数吗

使用特权

评论回复
17
skyred| | 2022-1-19 16:04 | 只看该作者
楼主,有个加代码的小工具,
发帖的时候,选用<>,可读性会很好

使用特权

评论回复
18
yizushijie| | 2022-3-19 14:10 | 只看该作者
硬件的iic我也调试通过。用的轮训模式,没用中断模式。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:绿水本无忧因风皱面,青山原不老为雪白头。

553

主题

3530

帖子

19

粉丝