打印
[STM32F1]

软件模拟IIC通讯

[复制链接]
652|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kkzz|  楼主 | 2023-11-14 12:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


void MyI2C_W_SCL(uint8_t BitValue);
void MyI2C_W_SDA(uint8_t BitValue);
uint8_t MyI2C_R_SDA(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
void MyI2C_SendBuffer(uint8_t *Buffer, uint32_t len);
void MyI2C_RecvBuffer(uint8_t I2C_Slave_Addr, uint8_t AR_Addr, uint8_t *Buffer, uint32_t len);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);


 


// 需要替换的函数
GPIO_WriteBit();         // 引脚电平写入函数
GPIO_ReadInputDataBit(); // 读引脚电平函数
Delay_us(10);            // 延迟函数
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 拉高拉低SCL
* @param {uint8_t} BitValue 0/1
* [url=home.php?mod=space&uid=266161]@return[/url] {*}
*/
void MyI2C_W_SCL(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
    Delay_us(10);
}
/**
* @brief : 拉高拉低SDA
* @param {uint8_t} BitValue 0/1
* @return {*}
*/
void MyI2C_W_SDA(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
    Delay_us(10);
}
/**
* @brief : 读SDA电平
* @return {*}
*/
uint8_t MyI2C_R_SDA(void)
{
    uint8_t BitValue;
    BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
    Delay_us(10);
    return BitValue;
}

void MyI2C_Init(void)
{
    /*使能外设时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /*结构体配置IIC引脚*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11); // 拉高引脚电平
}

/********************************************************************************************************************************************
修改上面的函数就行下面的都是封装好的
IIC通讯原则 发送起始信号 发送一个字节 接收应答标志 发送下一个字节 接收应答标志 发送停止标志
*******************************************************************************************************************************************/

/**
* @brief 发送开始标志
* @return {*}
*/
void MyI2C_Start(void)
{
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(0);
    MyI2C_W_SCL(0);
}
/**
* @brief 发送停止标志
* @return {*}
*/
void MyI2C_Stop(void)
{
    /*SCL高电平期间SDA由低变高*/
    MyI2C_W_SDA(0);
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(1);
}

/**
* @brief  起始位后SCL为低 可以放数据在SDA上,随后拉高SCL从机读取主机发送的数据,主机在拉低SCL进入下一位的发送
* @param {uint8_t} Byte
* @return {*}
*/
void MyI2C_SendByte(uint8_t Byte)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        MyI2C_W_SDA(Byte & (0x80 >> i));
        MyI2C_W_SCL(1);
        MyI2C_W_SCL(0);
    }
}
/**
* @brief  发送buffer
* @param {uint8_t} Byte
* @return {*}
*/
void MyI2C_SendBuffer(uint8_t *Buffer, uint32_t len)
{
    MyI2C_Start();
    for (int i = 0; i < len; i++)
    {
        MyI2C_SendByte(Buffer[i]);
        MyI2C_ReceiveAck();
    }
    MyI2C_Stop();
}
/**
* @brief : 接收指定从机寄存器地址的buffer
* @param {uint8_t} I2C_Slave_Addr 从机地址
* @param {uint8_t} AR_Addr  寄存器地址
* @param {uint8_t} *Buffer  数据
* @param {uint32_t} len  数据长度
* @return {*}
*/
void MyI2C_RecvBuffer(uint8_t I2C_Slave_Addr, uint8_t AR_Addr, uint8_t *Buffer, uint32_t len)
{

    MyI2C_Start();

    MyI2C_SendByte(I2C_Slave_Addr);
    MyI2C_ReceiveAck();
    MyI2C_SendByte(AR_Addr);
    MyI2C_ReceiveAck();

    MyI2C_Start();
    MyI2C_SendByte(I2C_Slave_Addr | 0x01);
    MyI2C_ReceiveAck();
    for (int i = 0; i < len; i++)
    {
        Buffer[i] = MyI2C_ReceiveByte();
        if (i == len - 1)
        {
            MyI2C_SendAck(1);
        }
        else
        {
            MyI2C_SendAck(0);
        }
    }

    MyI2C_Stop();
}

/**
* @brief  主机先拉高SDA是释放总线的意思,SCL此时为低 ,从机可以 放数据在SDA上,随后主机拉高SCL读取SDA的值在拉低SCL进入下一个周期
* @param {uint8_t} Byte
* @return {*}
*/
uint8_t MyI2C_ReceiveByte(void)
{
    uint8_t i, Byte = 0x00;
    MyI2C_W_SDA(1);
    for (i = 0; i < 8; i++)
    {
        MyI2C_W_SCL(1);
        if (MyI2C_R_SDA() == 1)
        {
            Byte |= (0x80 >> i);
        }
        MyI2C_W_SCL(0);
    }
    return Byte;
}
/**
* @brief  发送应答位
* @param {uint8_t} Byte 0应带继续接收,1不应答
* @return {*}
*/
void MyI2C_SendAck(uint8_t AckBit)
{
    MyI2C_W_SDA(AckBit);
    MyI2C_W_SCL(1);
    MyI2C_W_SCL(0);
}
/**
* @brief  发送应答位
* @param {uint8_t} Byte 0应带继续接收,1不应答
* @return {*}
*/
uint8_t MyI2C_ReceiveAck(void)
{
    uint8_t AckBit;
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);
    AckBit = MyI2C_R_SDA();
    MyI2C_W_SCL(0);
    return AckBit;
}


使用特权

评论回复
沙发
帛灿灿| | 2024-8-1 07:04 | 只看该作者

如果在编程时加密锁定位被使能/锁定,就无法用普通编程器直接读取单片机内的程序

使用特权

评论回复
板凳
Bblythe| | 2024-8-1 08:07 | 只看该作者

编程器定位插字节

使用特权

评论回复
地板
周半梅| | 2024-8-1 10:03 | 只看该作者

缩短距离较近的电容的寿命

使用特权

评论回复
5
Pulitzer| | 2024-8-1 11:06 | 只看该作者

利用协议、加密算法或这些算法中的安全漏洞来进行攻击

使用特权

评论回复
6
童雨竹| | 2024-8-1 13:02 | 只看该作者

大地的地会通过散热器(用绝缘体与漏极隔开)从这些节点获取能量

使用特权

评论回复
7
Wordsworth| | 2024-8-1 14:05 | 只看该作者

具存储功能的存储器芯片也能加密

使用特权

评论回复
8
Clyde011| | 2024-8-1 15:08 | 只看该作者

紫外光复位保护电路是不行的

使用特权

评论回复
9
公羊子丹| | 2024-8-1 16:01 | 只看该作者

交流节点会引起特有的问题

使用特权

评论回复
10
万图| | 2024-8-1 17:04 | 只看该作者

大部分能够读取或者识别Flash上的数据就能够获得Firmware文件

使用特权

评论回复
11
Uriah| | 2024-8-1 18:07 | 只看该作者

微探针技术都属于侵入型攻击

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

317

主题

10906

帖子

13

粉丝