当前位置: 首页 > news >正文

IIC协议-HAL库

  

 设置为开漏输出的好处是防止因为SDA是半双工,在没有同步好时同时输出出现的问题,CPU输出高电平,被控IC输出低电平时导致短路

SDA和SCL的上拉电阻非常重要!!!!!(在释放SDA/SCL,输出高阻态时自动拉到高电平)

 

时序:

 接收就是发送的反过程,不过接收要释放SDA,SCL仍由主机控制

 如果主机不想后续读了,就发非应答即可

 

每个IIC设备在出厂前都会给一个7位的地址,有些IIC设备的地址是可以修改某些位的的有对应的A0/A1/A2..引脚即可

指定地址写:

MPU6050为例

从机地址+读写位(用来确定主机是要读还是写)共八位

 

 

当前地址读:

(只能读当前地址指针下的地址,默认是0,如果你之前写过,当前地址指针会自增1)

(这个用的不多,因为不能指定读哪个地址)

 

 那么聪明的你肯定猜到了怎么指定地址读了吧

那肯定是指定写哪个寄存器然后重新开始Sr(start repeat),然后开始读,那不就完成了指定地址读了吗

软件模拟代码及OLED使用:

#include "sys.h"
#include "delay.h"

void iic2590_w_scl(int value)
{
    if (value == 0) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
    else HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
}
void iic2590_w_sda(int value)
{
    if (value == 0) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    else HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
}
uint8_t iic2590_r_sda(void)
{
    uint8_t BitValue;
    BitValue = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
    return BitValue;
}
void iic2590_init(void)
{
    //GPIOB1 SDA
    //GPIOB0 SCL
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIOBInit;
    GPIOBInit.Mode = GPIO_MODE_OUTPUT_OD;
    GPIOBInit.Pin = GPIO_PIN_0 | GPIO_PIN_1;
    GPIOBInit.Pull = GPIO_PULLUP;
    GPIOBInit.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB,&GPIOBInit);
}

void iic2590_start(void)
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
}
void iic2590_stop(void)
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
}
void iic2590_sendbyte(uint8_t Byte)
{
    for (int i =0;i<8;i++)
    {
        iic2590_w_sda(Byte & (0x80 >> i));
        iic2590_w_scl(1);
        iic2590_w_scl(0);
    }
}
uint8_t iic2590_receivebyte(void)
{
    uint8_t Byte = 0x00;
    iic2590_w_sda(1);
    for (int i=0;i<8;i++)
    {
        iic2590_w_scl(1);
        if (iic2590_r_sda() == 1) Byte |= (0x80 >> i);
        iic2590_w_scl(0);
    }
    return Byte;
}
void iic2590_sendack(uint8_t ackbit)
{
    iic2590_w_sda(ackbit);
    iic2590_w_scl(1);
    iic2590_w_scl(0);
}
uint8_t iic2590_receiveack(void)
{
    uint8_t ackbit;
    iic2590_w_sda(1);
    iic2590_w_scl(1);
    ackbit = iic2590_r_sda();
    iic2590_w_scl(0);
    return ackbit;
}
void Oled_Write_Cmd(char dataCmd)
{
     //  1. start()
     iic2590_start();
    //  2. 写入从机地址  b0111 1000 0x78
     iic2590_sendbyte(0x78);
     //  3. ACK
     iic2590_receiveack();
     //  4. cotrol byte: (0)(0)000000 写入命令   (0)(1)000000写入数据
    iic2590_sendbyte(0x00);
     //  5. ACK
     iic2590_receiveack();
     //6. 写入指令/数据
    iic2590_sendbyte(dataCmd);
     //7. ACK
     iic2590_receiveack();
     //8. STOP
     iic2590_stop();
}
void Oled_Write_Data(char dataData)
{
     //  1. start()
     iic2590_start();
    //  2. 写入从机地址  b0111 1000 0x78
     iic2590_sendbyte(0x78);
     //  3. ACK
     iic2590_receiveack();
     //  4. cotrol byte: (0)(0)000000 写入命令   (0)(1)000000写入数据
    iic2590_sendbyte(0x40);
     //  5. ACK
     iic2590_receiveack();
     //6. 写入指令/数据
    iic2590_sendbyte(dataData);
     //7. ACK
     iic2590_receiveack();
     //8. STOP
     iic2590_stop();
}
void Oled_Init(void)
{
    iic2590_init();
    Oled_Write_Cmd(0xAE);//--display off
    Oled_Write_Cmd(0x00);//---set low column address
    Oled_Write_Cmd(0x10);//---set high column address
    Oled_Write_Cmd(0x40);//--set start line address  
    Oled_Write_Cmd(0xB0);//--set page address
    Oled_Write_Cmd(0x81); // contract control
    Oled_Write_Cmd(0xFF);//--128   
    Oled_Write_Cmd(0xA1);//set segment remap 
    Oled_Write_Cmd(0xA6);//--normal / reverse
    Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
    Oled_Write_Cmd(0x3F);//--1/32 duty
    Oled_Write_Cmd(0xC8);//Com scan direction
    Oled_Write_Cmd(0xD3);//-set display offset
    Oled_Write_Cmd(0x00);//
    
    Oled_Write_Cmd(0xD5);//set osc division
    Oled_Write_Cmd(0x80);//
    
    Oled_Write_Cmd(0xD8);//set area color mode off
    Oled_Write_Cmd(0x05);//
    
    Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
    Oled_Write_Cmd(0xF1);//
    
    Oled_Write_Cmd(0xDA);//set com pin configuartion
    Oled_Write_Cmd(0x12);//
    
    Oled_Write_Cmd(0xDB);//set Vcomh
    Oled_Write_Cmd(0x30);//
    
    Oled_Write_Cmd(0x8D);//set charge pump enable
    Oled_Write_Cmd(0x14);//
    
    Oled_Write_Cmd(0xAF);//--turn on oled panel     
}
void Oled_Clear(void)
{
    unsigned char i,j; //-128 --- 127
    
    for(i=0;i<8;i++)
    {
        Oled_Write_Cmd(0xB0 + i);

        //page0--page7,哪一页1011 0xxx只有后三位代表页,前面都为固定格式
        //每个page从0列
        Oled_Write_Cmd(0x00);//0000 (0000),列地址的低4位是括号内的
        Oled_Write_Cmd(0x10);//0001 (0000),列地址的高4位是括号内的
        //0到127列,依次写入0,每写入数据,列地址自动偏移
        for(j = 0;j<128;j++)
            {
                Oled_Write_Data(0);
             }
     }
}
void Oled_show(char value)
{
    if (value == 'A')
    {
        Oled_Clear();
        /*-- 文字: A --*/
        /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16   --*/
        char A1[8] = {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00};
        char A2[8] = {0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};
        //2.2 选择PAGE0   1011 0000
        // 0xB0
        Oled_Write_Cmd(0xB0);
        Oled_Write_Cmd(0x00);
        Oled_Write_Cmd(0x10);
        for(int i=0;i<8;i++)
        {
                Oled_Write_Data(A1[i]);
        }
        //2.2 选择PAGE1   1011 0001
        // 0xB1
        Oled_Write_Cmd(0xB1);
        Oled_Write_Cmd(0x00);
        Oled_Write_Cmd(0x10);
        for(int i=0;i<8;i++)
        {
                Oled_Write_Data(A2[i]);
        }
    }
}

 

相关文章:

  • 在微信小程序或前端开发中,picker 和 select 都是用户交互中用于选择的组件,但它们在功能、设计和使用场景上有一定的区别
  • StarRocks + Paimon 在阿里集团 Lakehouse 的探索与实践
  • go回调函数的使用
  • 分而治之:用于 RGB-T 显著目标检测的 Confluent Triple-Flow 网络(问题)
  • 基于Babylon.js的Shader入门三(让Shader中的纹理动起来)
  • Jmeter的简单使用
  • STM32-SPI通信外设
  • Python 与 JavaScript 交互及 Web 逆向分析全解析
  • 3D文物线上展览如何实现?
  • 一些docker命令
  • L1正则化与L2正则化的区别
  • DataWhale 大语言模型 - 大模型技术基础
  • 数据库技术
  • EB-Cable许可与软件版本兼容性的关系
  • 常见的企业软件和工业软件种类
  • Springboot中的异常处理
  • 棒球和垒球区别·棒球1号位
  • Marp 高效 Markdown 幻灯片制作指南
  • 爱普生车规级晶振SG2520CAA智能汽车电子系统的应用
  • Java Stream API 的使用
  • 安徽凤阳通报鼓楼瓦片脱落:去年3月维修竣工,已成立调查组
  • 事关中国,“英伟达正游说美国政府”
  • 全国游泳冠军赛:孙杨、潘展乐同进400自决赛,今晚将正面对决
  • 国际金价下跌,中概股多数上涨,穆迪下调美国主权信用评级
  • 阿里上季度营收增7%:淘天营收创新高,AI产品营收连续七个季度三位数增长
  • 上海率先推进生物制品分段生产试点,这款国产1类创新药获批上市