首页 > 其他分享 >stm32硬件实现IIC

stm32硬件实现IIC

时间:2024-01-17 18:22:10浏览次数:32  
标签:硬件 CR1 IIC stm32 SR1 timeout I2C I2C2

#include "Driver_IIC.h"
#include "Delay.h"

/**
 * IIC默认地工作于从模式。
 *  生成起始条件后自动地从从模式切换到主模式,
 *  当仲裁丢失或产生停止信号时,从主模式切换到从模式。
 * 
 * 
 * 从模式用于接收数据;主模式用于发送数据。
*/


/**
 * 初始化
*/
void Driver_IIC_Init(void)
{
    /* 1.时钟控制使能IIC 和 GPIOB */
    RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    /* 2.配置PB10、PB11为复用开漏 */
        // PB10 和 PB11 引脚为 I2C2
    GPIOB->CRH |= ( GPIO_CRH_MODE10 | GPIO_CRH_CNF10 | GPIO_CRH_MODE11 | GPIO_CRH_CNF11 );

    /* 3.配置IIC, */
    // 3.0 配置SMBUS模式,0为IIC模式;1为SMBUS模式。
    I2C2->CR1 &= ~I2C_CR1_SMBUS;

    // 3.1 配置IIC时钟频率 FREQ
        // 这里就不先将0-5位清零了,直接 或 操作了。
    I2C2->CR2 |= 0x24;

    // 3.2 配置模式(标准模式/快速模式)
    I2C2->CCR &= ~I2C_CCR_FS;

    // 3.3 配置通讯速率(标准模式100KHz,快速模式400KHz), 
            // 计算为: CCR = Thigh / T  
            //  --->  100KHz/s 即 10us/1Hz, Thigh+Tlow=10us,Thigh=5us (即5us产生一个高电平)
            //  --->  T为周期(产生一个方波需要的时间) = 1s/f     f为频率,   即 1s/36MHz,即 1us/36Hz, 即 1/36us产生一个方波
            //  --->  CRR = 5 / (1/36) = 180
    I2C2->CCR |= 180;

    // 3.4 允许的SCL最大上升时间  TRISE = (最大上升沿时间/时钟周期)+1   (100KHz要求最大上升沿时间不超过1us)
    I2C2->TRISE |= 37;

    // 3.5 IIC使能PE
    I2C2->CR1 |= I2C_CR1_PE;

}

/**
 * 产生开始条件
 * 1成功;0失败
*/
uint8_t Driver_IIC_Start(void)
{
    /* 1.起始条件产生,无所谓主从,1就行 */
        // 起始条件产生后,就从从模式变成主模式了
    I2C2->CR1 |= I2C_CR1_START;

    /* 2.用SR1的SB位判断主模式起始条件,加个检测超时的变量判断*/
    uint16_t timeout = 0xffff;
    while(!(I2C2->SR1&I2C_SR1_SB) && timeout) {
        timeout--;
    }

    /* 3.返回开始条件是否返回成功 */
    return timeout ? 1: 0;
}

/**
 * 产生终止条件
*/
void Driver_IIC_Stop(void)
{
    /* 产生终止条件 */
        // 终止产生后,自动变为从模式
    I2C2->CR1 |= I2C_CR1_STOP;
}

/**
 * 产生应答
*/
void Driver_IIC_ACK(void)
{
    /* 产生应答信号 */
    I2C2->CR1 |= I2C_CR1_ACK;
}

/**
 * 产生无应答
*/
void Driver_IIC_NACK(void)
{
    /* 产生无应答信号 */
    I2C2->CR1 &= ~I2C_CR1_ACK;
}

/**
 * 发送地址
 * 发送成功返回1;失败返回0
*/
uint8_t Driver_IIC_SendAddr(uint8_t addr) {

    uint16_t timeout = 0xffff;
    while (((I2C2->SR1 & I2C_SR1_TXE) == 0) && timeout)
    {
        timeout--;
    }

    /* 把数据写入到数据寄存器中 */
    I2C2->DR = addr;

    /* 等待地址发送完成。*/
    timeout = 0xffff;
    while(!(I2C2->SR1 & I2C_SR1_ADDR) /* 地址还没有发送结束 */ && timeout) {
        timeout--;
    }
    // 走出循环后,如果timeout为0,则是超时了;如果timeout非0,则是发送结束了。
    if(timeout) {
        // 通过  读取SR1寄存器 再 读取SR2寄存器 对 ADDR寄存器进行清零
        // I2C2->SR1;
        I2C2->SR2;
        return 1;
    }
    return 0;
}

/**
 * 发送一个字节
 * 1成功;0失败
*/
uint8_t Driver_IIC_Transmit(uint8_t byte)
{
    /* 1.等待数据寄存器空 */
    uint16_t timeout = 0xffff;
    while(!(I2C2->SR1&I2C_SR1_TXE) && timeout) {
        timeout--;
    }
    if(!timeout) return 0;

    /* 2.往数据寄存器中写数据 */
    I2C2->DR = byte;

    /* 3. 通过SR1_BTF位判断数据是否发送结束,并返回 */
    timeout = 0xffff;
    while(!(I2C2->SR1&I2C_SR1_BTF) && timeout) {
        timeout--;
    }
    return timeout ? 1:0;
}

/**
 * 读取一个字节
*/
uint8_t Driver_IIC_ReadByte(void)
{
    /* 1.通过SR1_RxNE位判断数据寄存器是否非空 */
    uint16_t timeout = 0xffff;
    while(!(I2C2->SR1&I2C_SR1_RXNE) && timeout) {
        timeout--;
    }

    /* 2.根据判断结果返回数据寄存器中的值 */
    return timeout ? I2C2->DR : 0;
}



标签:硬件,CR1,IIC,stm32,SR1,timeout,I2C,I2C2
From: https://www.cnblogs.com/wangsiyaoa/p/17970700

相关文章

  • STM32系统开发--位、字节操作
    针对MCU的嵌入是开发中经常涉及到寄存器的操作,例如GPIO配置低寄存器GPIOx_CRL(共32个bit),有时需要改变其中的一位或者几位bit值,同时不能影响其它bit位的值。 例如,需要设置第0位bit=1时,不能简单的设置为:GPIOx_CRL=0x01,这样的方法会使得低配置寄存器GPIOx_CRL的其它比特位都置......
  • 实现连贯IT硬件资产管理的6个最佳实践
    随着业务的发展,对更好服务体验的需求成倍增加,服务运营必须跟上这一需求。此外,在应对持续的经济逆风和IT人才紧缩等全球挑战的同时,企业需要利用现有的IT投资实现更多目标。从配置IT资产和利用数据中心到确保跨区域的服务可用性,有凝聚力的IT资产管理策略可以帮助企业掌握这......
  • STM32CubeMX教程16 DAC - 输出3.3V内任意电压
    1、准备材料开发板(正点原子stm32f407探索者开发板V2.4)STM32CubeMX软件(Version6.10.0)keilµVision5IDE(MDK-Arm)ST-LINK/V2驱动野火DAP仿真器XCOMV2.6串口助手2、实验目标使用STM32CubeMX软件配置STM32F407开发板的DACOUT1实现输出0-3.3V任意模拟电压,然后用ADC1_IN5单通......
  • 在 STM32 中使用环形队列的方式接收串口数据
    在STM32中使用环形队列的方式接收串口数据#include<stdio.h>#include<stm32f10x.h>#include<stm32f10x_usart.h>//定义环形队列的结构体typedefstruct{uint8_t*buffer;//数据缓冲区uint16_tsize;//缓冲区大小uint16_tfront;//队列头索引......
  • Windows 硬件信息监控工具 OhmGraphite 部署
    1、下载OhmGraphitehttps://github.com/nickbabcock/OhmGraphite/releases2、修改OhmGraphite.exe.config配置(此处使用Prometheus做为数据源)<?xmlversion="1.0"encoding="utf-8"?><configuration><appSettings><addkey="t......
  • STM32
    STM321、keil的配置以及vscode的配置略2、stm32的命名规则todo以下以stm32lf103ze为例。3、点亮第一个小灯​ 开启时钟、设置输入/输出模式、给小灯的位赋值0。开启时钟开启时钟使用到的寄存器为RCC_APB2ENR,32位,高16位为保留位。第二位IOPA控制IO端口A的输入输出使能......
  • stm32笔记[11]-驱动SSD1306屏幕
    摘要在蓝桥杯物联网的CT127C开发板上驱动SSD1306的0.91寸显示屏.平台信息KeilMDK-ARM(μVision)V5.35.0.0STM32CubeMX6.2.1原理简介CT127C开发板简介蓝桥物联网竞赛实训装置省赛训练套装,适用于蓝桥杯大赛(电子类)物联网设计与开发科目竞赛训练及高校日常教学实训环......
  • IIC:DDM_SFP光模块参数读取
    光模块数字诊断监控数据读取逻辑报告I2C从设备地址0xA2访问的256字节的数据包括一些常量,也包含一些只读的变量,甚至还有一些可写的变量。数字诊断内存映射专用数据字段描述如下: 图1期间地址分布说明 图2检测信号地址 Finisar公司的DDM数据位于器件地址A2H,具体信号数据......
  • STM32学习Day1
    一.所用型号二.STM32上所拥有的外设三.各个引脚的定义(查表)颜色引脚类型蓝色最小相关系统的引脚绿色I/O口和功能口的引脚红色电源相关的引脚类型:①S表示电源②I表示输入③O表示输出I/O口电平:I/O口能容忍的电压FT表示容忍5V,无FT则为3.3V主......
  • LCD 硬件操作原理
    1、LCD显示原理  FrameBuffer即显存   SMT32与液晶控制芯片通过8080接口通讯,而液晶控制芯片包含显存、LCD控制器、LCD屏幕,液晶控制芯片常见有RA8875、ILI9341等芯片 嵌入式Linux则使用TFTRGB接口,内存和LCD控制器集成在Soc里面,外部接一个LCD屏幕。......