Cjy_JDxy 发表于 2019-9-30 20:21

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

今晚搞了一下软件模拟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;

/****************************************************************************
* 名    称: 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;

}
/**
******************************************************************************
** \briefMain 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=ReadChar(0);
    Delay(100);         //延时一段时间
    WriteChar(0,0x55);
    Delayms(20);
    WriteChar(1,0xaa);
    Delayms(20);
    WriteChar(2,0x27);
    Delayms(20);
    buffer=ReadChar(1);
    buffer=ReadChar(2);
    buffer=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

}

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

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
配置了呀

Cjy_JDxy 发表于 2019-12-28 15:07

martinhu 发表于 2019-9-30 23:35
楼主void InitSDAOutputH(void)和void InitSDAOutputL(void)是要初始化IO引脚并且初始化成高电平和低电平吗 ...

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

Cjy_JDxy 发表于 2020-1-8 18:07

第一次读,如果没写过,那就是0xff啊

updownq 发表于 2020-1-10 20:47

         

wengh2016 发表于 2020-1-10 20:47

谢谢分享的。         

qiufengsd 发表于 2020-1-10 20:48

没有硬件iic吗

kmzuaz 发表于 2020-1-10 20:48

楼主自己开发的iic吗?   

plsbackup 发表于 2020-1-10 20:48

看着好复杂了。   {:lol:}         

Cjy_JDxy 发表于 2020-1-11 07:59

qiufengsd 发表于 2020-1-10 20:48
没有硬件iic吗

有。

Cjy_JDxy 发表于 2020-1-11 08:00

kmzuaz 发表于 2020-1-10 20:48
楼主自己开发的iic吗?

模拟时序呀

nvjwiciw659 发表于 2020-4-21 18:24

多谢分享,很有用

米多0036 发表于 2020-4-22 22:39

就是0xff啊

18255236907 发表于 2021-12-9 12:35

不是都是封装库函数吗

skyred 发表于 2022-1-19 16:04

楼主,有个加代码的小工具,
发帖的时候,选用<>,可读性会很好

yizushijie 发表于 2022-3-19 14:10

硬件的iic我也调试通过。用的轮训模式,没用中断模式。
页: [1]
查看完整版本: 【HC32L136 demo板】+软件模拟I2C时序读写24C04