打印
[STM32G0]

天生残U,I2C双机通信之I2C从机

[复制链接]
1222|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zero949079783|  楼主 | 2023-11-12 18:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zero949079783 于 2023-11-24 22:51 编辑

天生残U,I2C双机通信之I2C从机
#include "i2c_drv.h"
#include "usart_drv.h"
I2C_HandleTypeDef i2c1;
I2C_HandleTypeDef i2c2;
DMA_HandleTypeDef i2c1_txdma;
DMA_HandleTypeDef i2c1_rxdma;
//uint8_t wdata[16] ={2,2,3,4,5,6,7,8,1,2,3,4,5,6,7,12};        //给从机发送数据
//uint8_t rdata[16] ={0};                                                                        //读取从机的数据
uint16_t i ;
uint8_t rx_flag=0;
uint8_t tx_data[21]={"01234567890abcdef123"};
uint8_t rx_data[20]={0};                                //接收缓冲区必需大于主机发送数据量,否则会一直进入中断

uint8_t tx_data2[21]={"01234567890abcdef123"};
uint8_t rx_data2[20]={0};
//uint8_t reg_data[1];
#define slave_addr (0x01<<1)
#define slave_addr2 (0x02<<1)
void i2c_reset();

void I2C_Drv_Init(void)
{
        uint8_t i;
        i2c1.Instance = I2C1;
        i2c1.Init.Timing=0x00602173;
        //i2c1.Init.Timing = 0xC010EBFF;
        i2c1.Init.OwnAddress1 = slave_addr;                        //从机地址
        i2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
        i2c1.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
        i2c1.Init.OwnAddress2 = slave_addr2;
        i2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
        i2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
        
        HAL_I2C_Init(&i2c1);

        i2c2.Instance = I2C2;
        i2c2.Init.Timing=0x00602173;
        //i2c1.Init.Timing = 0xC010EBFF;
        i2c2.Init.OwnAddress1 = slave_addr;                        //从机地址
        i2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
        i2c2.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
        i2c2.Init.OwnAddress2 = slave_addr2;
        i2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
        i2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
        
//        HAL_I2C_Init(&i2c2);        
//        for(i=0;i<21;i++)
//        {
//                tx_data[i]=21-i;
//        }
//        
//        for(i=0;i<21;i++)
//        {
//                tx_data2[i]=21-i;
//        }        
        
        HAL_I2C_EnableListen_IT(&i2c1);        //启动侦听地址
        
        HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
}

void I2C_Drv_Init2(void)
{


        i2c2.Instance = I2C2;
        i2c2.Init.Timing=0x00602173;
        //i2c1.Init.Timing = 0xC010EBFF;
        i2c2.Init.OwnAddress1 = slave_addr;                        //从机地址
        i2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
        i2c2.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
        i2c2.Init.OwnAddress2 = slave_addr2;
        i2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
        i2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
        
        HAL_I2C_Init(&i2c2);        

        
        HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
}

void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
        GPIO_InitTypeDef GPIO_InitTypeDefStructur;
        
        if(hi2c ->Instance == I2C1)
        {
                __HAL_RCC_I2C1_CLK_ENABLE();
                __HAL_RCC_GPIOB_CLK_ENABLE();

                GPIO_InitTypeDefStructur.Pin =GPIO_PIN_8|GPIO_PIN_9;
                GPIO_InitTypeDefStructur.Mode = GPIO_MODE_AF_OD;
                GPIO_InitTypeDefStructur.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
                GPIO_InitTypeDefStructur.Pull=GPIO_NOPULL;
                GPIO_InitTypeDefStructur.Alternate=GPIO_AF6_I2C1;               
                HAL_GPIO_Init(GPIOB,&GPIO_InitTypeDefStructur);               
               
                HAL_NVIC_SetPriority(I2C1_IRQn,0,2);
                HAL_NVIC_EnableIRQ(I2C1_IRQn);        

                __I2C1_FORCE_RESET();
                __I2C1_RELEASE_RESET();
               
                hi2c->Instance->CR1 = I2C_CR1_SWRST;   //复位I2C
                hi2c->Instance->CR1 = 0;              //解除复位               
//                //I2C RX
//                i2c1_txdma.Instance = DMA1_Channel2;
//                i2c1_txdma.Init.Request = DMA_REQUEST_I2C1_TX;
//                i2c1_txdma.Init.Direction = DMA_MEMORY_TO_PERIPH;
//                i2c1_txdma.Init.PeriphInc = DMA_PINC_DISABLE;
//                i2c1_txdma.Init.MemInc = DMA_MINC_ENABLE;
//                i2c1_txdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
//                i2c1_txdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
//                i2c1_txdma.Init.Mode = DMA_NORMAL;
//                i2c1_txdma.Init.Priority = DMA_PRIORITY_MEDIUM;

//                __HAL_LINKDMA(hi2c,hdmatx,i2c1_txdma);        
//                HAL_DMA_Init(&i2c1_txdma);
//               
//                //I2C RX
//                i2c1_rxdma.Instance = DMA1_Channel3;
//                i2c1_rxdma.Init.Request = DMA_REQUEST_I2C1_RX;
//                i2c1_rxdma.Init.Direction = DMA_PERIPH_TO_MEMORY;
//                i2c1_rxdma.Init.PeriphInc = DMA_PINC_DISABLE;
//                i2c1_rxdma.Init.MemInc = DMA_MINC_ENABLE;
//                i2c1_rxdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
//                i2c1_rxdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
//                i2c1_rxdma.Init.Mode = DMA_NORMAL;
//                i2c1_rxdma.Init.Priority = DMA_PRIORITY_MEDIUM;


//                __HAL_LINKDMA(hi2c,hdmarx,i2c1_rxdma);               
//                HAL_DMA_Init(&i2c1_rxdma);
//                HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
//                HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);               
        }
        if(hi2c ->Instance == I2C2)
        {
                __HAL_RCC_I2C2_CLK_ENABLE();
                __HAL_RCC_GPIOA_CLK_ENABLE();

                GPIO_InitTypeDefStructur.Pin =GPIO_PIN_11|GPIO_PIN_12;
                GPIO_InitTypeDefStructur.Mode = GPIO_MODE_AF_OD;
                GPIO_InitTypeDefStructur.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
                GPIO_InitTypeDefStructur.Pull=GPIO_PULLUP;
                GPIO_InitTypeDefStructur.Alternate=GPIO_AF6_I2C2;               
                HAL_GPIO_Init(GPIOA,&GPIO_InitTypeDefStructur);               
               
                HAL_NVIC_SetPriority(I2C2_IRQn,0,1);
                HAL_NVIC_EnableIRQ(I2C2_IRQn);        

                __I2C2_FORCE_RESET();
                __I2C2_RELEASE_RESET();
               
                hi2c->Instance->CR1 = I2C_CR1_SWRST;   //复位I2C
                hi2c->Instance->CR1 = 0;
        }               
}

void i2c_reset()
{
    /* 开漏输出,关闭I2C输入通道,并尝试将总线拉高 */
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);

    // SCL PB8 拉高
    for (uint8_t i = 0; i < 10; i++) {

        if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
        {
            //rt_kprintf("retry %d\n", i);
            break;
        }
        /* 该延时循环的周期和时长,请根据你的实际主机对I2C通讯出错的处理来修改 */
        HAL_Delay(10);
    }

    /* 归还总线控制权 */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* 复位I2C */
    i2c1.Instance->CR1 |= I2C_CR1_SWRST;
    i2c1.Instance->CR1 &= ~I2C_CR1_SWRST;

    /* 重新初始化I2C */
   I2C_Drv_Init();
}
//侦听完成
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
        if(hi2c ->Instance == I2C1)
        {
                HAL_I2C_EnableListen_IT(&i2c1);        //启动侦听地址
                u1_printf("I2C1侦听地址完成\r\n");
        }
        else if(hi2c ->Instance == I2C2)
        {
                HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
                u1_printf("I2C2侦听地址完成\r\n");
        }        

}

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
        if(hi2c ->Instance == I2C1)
        {
                if((AddrMatchCode == slave_addr) || (AddrMatchCode == slave_addr2))
                {
                        if(TransferDirection ==I2C_DIRECTION_RECEIVE)        //准备给主机发送数据
                        {
                                        if(rx_data[0]==0x01)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,tx_data,2,I2C_LAST_FRAME);
                                                //HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data,1);
                                        }
                                        if(rx_data[0]==0x08)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,&tx_data[3],2,I2C_LAST_FRAME);
                                        }
                                        if(rx_data[0]==0x21)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data,21,I2C_LAST_FRAME);
                                        }                                                
                                        else
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,&tx_data[3],2,I2C_LAST_FRAME);
                                        }

                                       
                                //HAL_I2C_Slave_Transmit_DMA(&i2c1,wdata,16);
                                //        HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data[1],2);
                        }else if(TransferDirection == I2C_DIRECTION_TRANSMIT )        //准备接收主机的数据
                        {

                                
                                HAL_I2C_Slave_Seq_Receive_IT(&i2c1,rx_data,1,I2C_FIRST_FRAME);

                        }
                }
               
        }
        if(hi2c ->Instance == I2C2)
        {
                if((AddrMatchCode == slave_addr) || (AddrMatchCode == slave_addr2))
                {
                        if(TransferDirection ==I2C_DIRECTION_RECEIVE)        //准备给主机发送数据
                        {
                                        if(rx_data2[0]==0x01)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data2,2,I2C_LAST_FRAME);
                                                //HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data,1);
                                        }
                                        else if(rx_data2[0]==0x08)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[3],2,I2C_LAST_FRAME);
                                        }
                                        else if(rx_data2[0]==0x09)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[5],2,I2C_LAST_FRAME);
                                        }                                       
                                        else if(rx_data2[0]==0x21)
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data2,21,I2C_LAST_FRAME);
                                        }                                       
                                        else
                                        {
                                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[7],2,I2C_LAST_FRAME);
                                        }

                        }else if(TransferDirection == I2C_DIRECTION_TRANSMIT )        //准备接收主机的数据
                        {

                                
                                HAL_I2C_Slave_Seq_Receive_IT(&i2c2,rx_data2,1,I2C_FIRST_FRAME);

                        }
                }
        }        
                        
}

//从机发送完成
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
        if(hi2c ->Instance == I2C1)
        {
//                hi2c ->PreviousState = HAL_I2C_MODE_NONE;
                u1_printf("从机发送完成\r\n");
        }
        if(hi2c ->Instance == I2C2)
        {
//                hi2c ->PreviousState = HAL_I2C_MODE_NONE;
                u1_printf("从机发送完成\r\n");
        }        
}

//从机接收完成
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
        if(hi2c ->Instance == I2C1)
        {
                        hi2c ->PreviousState = HAL_I2C_MODE_NONE;
//
//                        u1_printf("从机接收中断完成 %d\r\n",__HAL_I2C_GET_FLAG(hi2c,I2C_FLAG_BUSY));
                //u1_printf("从机接收完成 %d\r\n",rx_data[0]);
                rx_flag=0;
//                        if(rx_data[0] == 0x01)
//                        {
//                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,tx_data,1,I2C_FIRST_AND_LAST_FRAME);
//                        }

               

                                u1_printf("rx_data%X\r\n",rx_data[0]);        
                        
               
        }
        else if(hi2c ->Instance == I2C2){

                        u1_printf("OK2\n") ;
                //u1_printf("从机接收完成 %d\r\n",rx_data[0]);               
        }
}

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
        if(hi2c ->Instance == I2C1)
        {
//                i2c_reset();
//                I2C_Drv_Init();
        }
}


使用特权

评论回复
沙发
一秒落纱| | 2023-11-20 22:14 | 只看该作者
怎么说?你说的G0的I2C不好用?

使用特权

评论回复
板凳
三生万物| | 2023-11-21 01:00 | 只看该作者
其实这个I2C不如用模拟的,时序搞好,其他都OK

使用特权

评论回复
地板
暖了夏天蓝了海| | 2023-11-21 03:00 | 只看该作者
你说的残,怎么个残法?

使用特权

评论回复
5
冰春彩落下| | 2023-11-21 05:00 | 只看该作者
是这芯片的I2C的从机模式不能用?

使用特权

评论回复
6
远山寻你| | 2023-11-21 07:00 | 只看该作者
应该用cubemx来配置一下的话,应该是没问题的吧

使用特权

评论回复
7
江河千里| | 2023-11-21 09:00 | 只看该作者
都是有BUG的存在,只是有没有弥补方法而已

使用特权

评论回复
8
淡漠安然| | 2023-11-21 11:00 | 只看该作者
给我的感觉就是这芯片就是为了更换STM32F1的,所以,有的可能这个U也是有I2C的问题吧

使用特权

评论回复
9
别乱了阵脚| | 2023-11-21 13:00 | 只看该作者
我建议还是楼主用模拟的方式实现I2C从机,但就是挂载不了了

使用特权

评论回复
10
光辉梦境| | 2023-11-21 15:00 | 只看该作者
哈哈,确实,ST的I2C总是备受争议

使用特权

评论回复
11
夜阑风雨| | 2023-11-21 22:00 | 只看该作者
你换个芯片呗,他家的I2C好像一直都有BUG吧

使用特权

评论回复
12
zero949079783|  楼主 | 2023-11-24 22:48 | 只看该作者
淡漠安然 发表于 2023-11-21 11:00
给我的感觉就是这芯片就是为了更换STM32F1的,所以,有的可能这个U也是有I2C的问题吧 ...

是有问题,数据接收少了,就死机

使用特权

评论回复
13
zero949079783|  楼主 | 2023-11-24 22:49 | 只看该作者
远山寻你 发表于 2023-11-21 07:00
应该用cubemx来配置一下的话,应该是没问题的吧

一样有问题

使用特权

评论回复
14
zero949079783|  楼主 | 2023-11-24 22:50 | 只看该作者
三生万物 发表于 2023-11-21 01:00
其实这个I2C不如用模拟的,时序搞好,其他都OK

你有没有I2C从机的模拟程序????

使用特权

评论回复
15
Pulitzer| | 2024-7-21 07:14 | 只看该作者

减小检测部分与电压误差或电流放大器敏感的输入端之间的连接而引入的噪声

使用特权

评论回复
16
童雨竹| | 2024-7-21 09:10 | 只看该作者

引线越长,它能接收和传送的干扰信号频率就越低

使用特权

评论回复
17
公羊子丹| | 2024-7-21 12:09 | 只看该作者

引线的长和宽影响它的电阻和电感量

使用特权

评论回复
18
万图| | 2024-7-21 13:12 | 只看该作者

它们的放置要尽可能靠近

使用特权

评论回复
19
Uriah| | 2024-7-21 14:15 | 只看该作者

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

使用特权

评论回复
20
帛灿灿| | 2024-7-21 16:11 | 只看该作者

输入电源电流环路

使用特权

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

本版积分规则

33

主题

89

帖子

1

粉丝