你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

NUCLEO-L552ZE-Q开发板模拟I2C的实验

[复制链接]
老牛洋车 提问时间:2024-12-31 13:48 / 未解决

一块闲置的NUCLEO-L552ZE-Q开发板需要驱动DS1307日历芯片,启用了硬件I2C,但尝试多次都没有读出数据,于是便启用模拟I2C。经过仔细调试,终于顺利地完成了对DS1307日历芯片的读写操作,下面是模拟I2C操作的时序图:

STM32L552_DS1307Read.png

下面是模拟I2C及对DS1307读写操作的代码:


/******************************************************
*程 序 名:void SI2C_SDA_Dir(uint8_t dir)
*作    用:设置SDA引脚读写方向
*输入参数:dir: 0=写(输出) 1=读(输入)
*返回参数:无
******************************************************/
void SI2C_SDA_Dir(uint8_t dir)                     //设置SDA的读写模式
{
    GPIO_InitTypeDef GPIO_InitStruct;
    if(dir == 0){
        GPIO_InitStruct.Pin = S_SDA_Pin;           //DIO输出模式、弱上拉
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(S_SDA_GPIO_Port, &GPIO_InitStruct);
    }
    else{
        GPIO_InitStruct.Pin = S_SDA_Pin;           //DIO输入模式
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        HAL_GPIO_Init(S_SDA_GPIO_Port, &GPIO_InitStruct);
    }
    HAL_GPIO_WritePin(S_SDA_GPIO_Port,S_SDA_Pin,GPIO_PIN_SET);
}

void SI2C_Start(void)
{
    SI2C_SDA_Dir(0);
    SDA_SET();
    SCL_SET();
    Delay_us(1);
    SDA_RESET();
    Delay_us(1);
    SCL_RESET();
    Delay_us(3);
}

void SI2C_Stop(void)
{
    SI2C_SDA_Dir(0);
    SDA_RESET();
    Delay_us(2);
    SCL_SET();
    Delay_us(1);
    SDA_SET();
}

void SI2C_Ack(void)
{
    SCL_RESET();
    SI2C_SDA_Dir(0);
    SDA_RESET();
    Delay_us(1);
    SCL_SET();
    Delay_us(5);
    SCL_RESET();
    Delay_us(2);
}

void SI2C_NoAck(void)
{
    SCL_RESET();
    SDA_SET();
    SI2C_SDA_Dir(0);
    Delay_us(1);
    SCL_SET();
    Delay_us(5);
    SCL_RESET();
}

uint8_t SI2C_IsAck(void)
{
    uint8_t i=0;
    SCL_RESET();
    SI2C_SDA_Dir(0);
    SDA_SET();                            //释放数据线
    SI2C_SDA_Dir(1);
    SCL_SET();
    Delay_us(1);
    while(HAL_GPIO_ReadPin(S_SDA_GPIO_Port,S_SDA_Pin)){
        i++;
        if(i>250){
            SI2C_Stop();
            return 1;
        }
    }
    SCL_RESET();
    SI2C_SDA_Dir(0);
    return 0;
}

/*****************************************************************************
* 函数名称:uint8_t SI2C_ReadByte(void)
* 函数功能:读取I2C设备数据
* 入口参数:无
* 出口参数:无
* 备    注:无
*****************************************************************************/
uint8_t SI2C_ReadByte(void)
{
    uint8_t dat,i;
    SI2C_SDA_Dir(1);
    for(i=0; i<8; i++){
        dat<<=1;
        SCL_SET();
        Delay_us(5);
        dat|=HAL_GPIO_ReadPin(S_SDA_GPIO_Port,S_SDA_Pin);
        SCL_RESET();
        Delay_us(5);
    }
    return  dat;
}

/*****************************************************************************
* 函数名称:uint8_t SI2C_WriteByte(uint8_t dat)
* 函数功能:向I2C写入8Bit数据,返回成功结果
* 入口参数:dat 要写入的数据
* 出口参数:返回 0=写成功,1=写失败
* 备    注:无
*****************************************************************************/
uint8_t SI2C_WriteByte(uint8_t dat)
{
    uint8_t i;
    SCL_RESET();
    SI2C_SDA_Dir(0);
    for(i=0; i<8; i++){
        if((dat & 0x80)>>7)
            SDA_SET();
        else
            SDA_RESET();
        SCL_SET();
        Delay_us(5);
        SCL_RESET();
        Delay_us(5);
        dat<<=1;
    }
    return  0;
}

/****************************************************************************************** 
* 函数名称: DS1307_Read()
* 功能说明: 从DS1307地址addr开始获取size个字节的数据,获取的数据存储在全局变量DS_Buff中
* 输    入: uint8_t addr  获取数据从addr开始
*           uint8_t size    要获取的数据个数(1~8)
* 输    出: ui08    0=RET_OK 成功从DS1307获取数据  1=RET_ERR 从DS1307获取数据过程中出现错误
******************************************************************************************/
uint8_t DS1307_Read(uint8_t addr,uint8_t size)
{
    uint8_t i = 0;
    SI2C_Start();                   //产生起始信号
    SI2C_WriteByte(addr);           //发送DS1307芯片地址及读写位,0表示写
    if(1 == SI2C_IsAck())           //检测DS1307是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 2;
    }
    SI2C_WriteByte(0);              //发送读取数据的起始地址
    if(1 == SI2C_IsAck())           //检测DS1307是否有响应
    {
        SI2C_Stop();                  //产生停止信号
        return 3;
    }

    SI2C_Start();                   //产生Repeated Start
    SI2C_WriteByte(addr|1);         //发送DS1307芯片地址及读写位,1表示读
    if(1 == SI2C_IsAck())           //检测DS1307是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 4;
    }

    for(i=0;size>0;i++,size--)        //从addr处读取size个字节的数据
    {
        DS_Buff[i] = SI2C_ReadByte();
        SI2C_Ack();
    }
    SI2C_NoAck();                   //DS1307要求必须使用NOAck来结束数据读取

    SI2C_Stop();                    //产生停止信号
    return 0;
}


/********************************************************************************************** 
* 函数名称: DS1307_Write()
* 功能说明: 向DS1307地址addr开始写入size个字节的数据,将要写入的数据存储在全局变量DS_Buff中
* 输    入: uint8_t addr  数据被写入从addr开始的地址处
*           uint8_t dat   数组 
*           uint8_t size    要设置的数据个数(1~8)
* 输    出: uint8_t       0=RET_OK 成功向DS1307设置数据  1=RET_ERR 向DS1307设置数据过程中出现错误
**********************************************************************************************/
uint8_t DS1307_Write(uint8_t addr,uint8_t *dat,uint8_t size)
{
    uint8_t i = 0;

    SI2C_Start();                   //产生起始信号
    SI2C_WriteByte(addr);           //发送DS1307芯片地址及读写位,0表示写
    if(1 == SI2C_IsAck())           //检测DS1307是否有响应
    {
        SI2C_Stop();                //产生停止信号
        return 1;
    }

    for(i=0; i<size; i++)
    {
        SI2C_WriteByte(dat[i]);
        if(1 == SI2C_IsAck())       //检测DS1307是否有响应
        {
            SI2C_Stop();            //产生停止信号
            return 3;
        }
    }

    SI2C_Stop();                    //产生停止信号
    return 0;
}

收藏 评论3 发布时间:2024-12-31 13:48

举报

3个回答
星海灿烂 回答时间:5 天前

大佬,又解决了一个问题,👍

〃聪聪哥哥 回答时间:5 天前

按说硬件IIC更好用一些啊?是不是配置的速度有问题?抓下波形看看啊

老牛洋车 回答时间:5 天前

〃聪聪哥哥 发表于 2024-12-31 16:10
按说硬件IIC更好用一些啊?是不是配置的速度有问题?抓下波形看看啊
...

是的,下一步准备继续测试硬件I2C,充分发挥MCU的性能。

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版