小工具知识网

当前位置: 首页 > 行业知识 > stm32——hal库学习笔记(IIC)

行业知识

stm32——hal库学习笔记(IIC)

2026-11-02 09:38:48 来源:互联网转载

一、IIC总线协议介绍(掌握)

二、AT24C02介绍(了解)

三、AT24C02读写时序(掌握)

四、AT24C02驱动步骤(掌握)

五、编程实战(掌握)

myiic.c

#include "./BSP/IIC/myiic.h"#include "./SYSTEM/delay/delay.h"/** * @brief       初始化IIC * @param       无 * @retval      无 */void iic_init(void){    GPIO_InitTypeDef gpio_init_struct;    IIC_SCL_GPIO_CLK_ENABLE();  /* SCL引脚时钟使能 */    IIC_SDA_GPIO_CLK_ENABLE();  /* SDA引脚时钟使能 */    gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出 */    gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;      /* 高速 */    HAL_GPIO_Init(IIC_SCL_GPIO_PORT, &gpio_init_struct);/* SCL */    gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;        /* 开漏输出 */    HAL_GPIO_Init(IIC_SDA_GPIO_PORT, &gpio_init_struct);/* SDA */    /* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */    iic_stop();     /* 停止总线上所有设备 */}/** * @brief       IIC延时函数,用于控制IIC读写速度 * @param       无 * @retval      无 */static void iic_delay(void){    delay_us(2);    /* 2us的延时, 读写速度在250Khz以内 */}/** * @brief       产生IIC起始信号 * @param       无 * @retval      无 */void iic_start(void){    IIC_SDA(1);    IIC_SCL(1);    iic_delay();    IIC_SDA(0);     /* START信号: 当SCL为高时, SDA从高变成低, 表示起始信号 */    iic_delay();    IIC_SCL(0);     /* 钳住I2C总线,准备发送或接收数据 */    iic_delay();}/** * @brief       产生IIC停止信号 * @param       无 * @retval      无 */void iic_stop(void){    IIC_SDA(0);     /* STOP信号: 当SCL为高时, SDA从低变成高, 表示停止信号 */    iic_delay();    IIC_SCL(1);    iic_delay();    IIC_SDA(1);     /* 发送I2C总线结束信号 */    iic_delay();}/** * @brief       等待应答信号到来 * @param       无 * @retval      1,接收应答失败 *              0,接收应答成功 */uint8_t iic_wait_ack(void){    uint8_t waittime = 0;    uint8_t rack = 0;    IIC_SDA(1);     /* 主机释放SDA线(此时外部器件可以拉低SDA线) */    iic_delay();    IIC_SCL(1);     /* SCL=1, 此时从机可以返回ACK */    iic_delay();    while (IIC_READ_SDA)    /* 等待应答 */    {        waittime++;        if (waittime > 250)        {            iic_stop();            rack = 1;            break;        }    }    IIC_SCL(0);     /* SCL=0, 结束ACK检查 */    iic_delay();    return rack;}/** * @brief       产生ACK应答 * @param       无 * @retval      无 */void iic_ack(void){    IIC_SDA(0);     /* SCL 0 -> 1  时 SDA = 0,表示应答 */    iic_delay();    IIC_SCL(1);     /* 产生一个时钟 */    iic_delay();    IIC_SCL(0);    iic_delay();    IIC_SDA(1);     /* 主机释放SDA线 */    iic_delay();}/** * @brief       不产生ACK应答 * @param       无 * @retval      无 */void iic_nack(void){    IIC_SDA(1);     /* SCL 0 -> 1  时 SDA = 1,表示不应答 */    iic_delay();    IIC_SCL(1);     /* 产生一个时钟 */    iic_delay();    IIC_SCL(0);    iic_delay();}/** * @brief       IIC发送一个字节 * @param       data: 要发送的数据 * @retval      无 */void iic_send_byte(uint8_t data){    uint8_t t;        for (t = 0; t > 7);    /* 高位先发送 */        iic_delay();        IIC_SCL(1);        iic_delay();        IIC_SCL(0);        data     uint8_t i, receive = 0;    for (i = 0; i  8)     /* 原理说明见:at24cxx_read_one_byte函数, 本函数完全类似 */    iic_start();                /* 发送起始信号 */    if (EE_TYPE  AT24C16)      /* 24C16以上的型号, 分2个字节发送地址 */    {        iic_send_byte(0XA0);    /* 发送写命令, IIC规定最低位是0, 表示写入 */        iic_wait_ack();         /* 每次发送完一个字节,都要等待ACK */        iic_send_byte(addr >> 8);/* 发送高字节地址 */    }    else     {        iic_send_byte(0XA0 + ((addr >> 8)     uint8_t temp;    uint16_t addr = EE_TYPE;    temp = at24cxx_read_one_byte(addr); /* 避免每次开机都写AT24CXX */    if (temp == 0X55)   /* 读取数据正常 */    {        return 0;    }    else    /* 排除第一次初始化的情况 */    {        at24cxx_write_one_byte(addr, 0X55); /* 先写入数据 */        temp = at24cxx_read_one_byte(255);  /* 再读取数据 */        if (temp == 0X55)return 0;    }    return 1;}/** * @brief       在AT24CXX里面的指定地址开始读出指定个数的数据 * @param       addr    : 开始读出的地址 对24c02为0~255 * @param       pbuf    : 数据数组首地址 * @param       datalen : 要读出数据的个数 * @retval      无 */void at24cxx_read(uint16_t addr, uint8_t *pbuf, uint16_t datalen){    while (datalen--)    {        *pbuf++ = at24cxx_read_one_byte(addr++);    }}/** * @brief       在AT24CXX里面的指定地址开始写入指定个数的数据 * @param       addr    : 开始写入的地址 对24c02为0~255 * @param       pbuf    : 数据数组首地址 * @param       datalen : 要写入数据的个数 * @retval      无 */void at24cxx_write(uint16_t addr, uint8_t *pbuf, uint16_t datalen){    while (datalen--)    {        at24cxx_write_one_byte(addr, *pbuf);        addr++;        pbuf++;    }}"STM32 IIC TEST"};#define TEXT_SIZE       sizeof(g_text_buf)  /* TEXT字符串长度 */int main(void){    uint8_t key;    uint16_t i = 0;    uint8_t datatemp[TEXT_SIZE];    HAL_Init();                                 /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */    delay_init(72);                             /* 延时初始化 */    usart_init(115200);                         /* 串口初始化为115200 */    usmart_dev.init(72);                        /* 初始化USMART */    led_init();                                 /* 初始化LED */    lcd_init();                                 /* 初始化LCD */    key_init();                                 /* 初始化按键 */    at24cxx_init();                             /* 初始化24CXX */    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);    lcd_show_string(30, 70, 200, 16, 16, "IIC TEST", RED);    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 110, 200, 16, 16, "KEY1:Write  KEY0:Read", RED);    /* 显示提示信息 */    while (at24cxx_check()) /* 检测不到24c02 */    {        lcd_show_string(30, 130, 200, 16, 16, "24C02 Check Failed!", RED);        delay_ms(500);        lcd_show_string(30, 130, 200, 16, 16, "Please Check!      ", RED);        delay_ms(500);        LED0_TOGGLE();      /* 红灯闪烁 */    }    lcd_show_string(30, 130, 200, 16, 16, "24C02 Ready!", RED);    while (1)    {        key = key_scan(0);        if (key == KEY1_PRES)   /* KEY1按下,写入24C02 */        {            lcd_fill(0, 150, 239, 319, WHITE);  /* 清除半屏 */            lcd_show_string(30, 150, 200, 16, 16, "Start Write 24C02....", BLUE);            at24cxx_write(0, (uint8_t *)g_text_buf, TEXT_SIZE);            lcd_show_string(30, 150, 200, 16, 16, "24C02 Write Finished!", BLUE);   /* 提示传送完成 */        }        if (key == KEY0_PRES)   /* KEY0按下,读取字符串并显示 */        {            lcd_show_string(30, 150, 200, 16, 16, "Start Read 24C02.... ", BLUE);            at24cxx_read(0, datatemp, TEXT_SIZE);            lcd_show_string(30, 150, 200, 16, 16, "The Data Readed Is:  ", BLUE);   /* 提示传送完成 */            lcd_show_string(30, 170, 200, 16, 16, (char *)datatemp, BLUE);          /* 显示读到的字符串 */        }        i++;        if (i == 20)        {            LED0_TOGGLE();  /* 红灯闪烁 */            i = 0;        }        delay_ms(10);    }}

上一篇:轻松掌握!教你如何轻松下载Updown指南!

下一篇:《MATLAB Simulink中的转速电流双闭环直流调速系统仿真及分析》