CH32v307V_R1 開發(fā)板使用硬件IIC,一直報busy

CH32v307V_R1 開發(fā)板使用CH32V307EVT 中的IIC例程I2C_EEPROM,用硬件IIC,一直報busy,測量示波器波形PB10和PB11都是低電平

代碼如下

/*

?* bsp_i2c.c

?*

?*? Created on: May 13, 2024

?*? ? ? Author: mx

?*/



/********************************** (C) COPYRIGHT *******************************

* File Name? ? ? ? ? : main.c

* Author? ? ? ? ? ? ?: WCH

* Version? ? ? ? ? ? : V1.0.0

* Date? ? ? ? ? ? ? ?: 2024/03/05

* Description? ? ? ? : Main program body.

*********************************************************************************

* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.

* Attention: This software (modified or not) and binary are used for

* microcontroller manufactured by Nanjing Qinheng Microelectronics.

*******************************************************************************/


/*

?*@Note

?I2C interface routine to operate EEPROM peripheral.

?I2C1_SCL(PB10)\I2C1_SDA(PB11).

?This example uses EEPROM for AT24Cxx series.

?Steps:

?READ EEPROM:Start + 0xA0 + 8bit Data Address + Start + 0xA1 + Read Data + Stop.

?WRITE EERPOM:Start + 0xA0 + 8bit Data Address + Write Data + Stop.


*/

#include "bsp_i2c.h"

#include "debug.h"

#include "FreeRTOS.h"

#include "task.h"

/**********************************************************************

*@Note:

AT24Cxx


READ EEPROM:Start + 0xA0 + 8bit Data Address + Start + 0xA1 + Read Data + Stop.

WRITE EERPOM:Start + 0xA0 + 8bit Data Address + Write Data + Stop.

*******************************************************************************/

/* EERPOM DATA ADDRESS Length Definition */

#define Address_8bit? ? ?0

#define Address_16bit? ? 1


/* EERPOM DATA ADDRESS Length Selection */

#define Address_Lenth? ? Address_8bit

//#define Address_Lenth? ?Address_16bit


/* Global define */

#define SIZE? ? ? ? ? ? ?sizeof(TEXT_Buffer)


/* Global Variable */

const u8 TEXT_Buffer[] = {"CH32F10x I2C TEST"};



/**

?* @brief IIC初始化

?*?

?* @param bound 速率

?* @param address 地址

?*/

void IIC_Init(u32 bound, u16 address)

{

? ? GPIO_InitTypeDef GPIO_InitStructure = {0};

? ? I2C_InitTypeDef? I2C_InitTSturcture = {0};


? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

? ? RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);


? ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

? ? GPIO_Init(GPIOB, &GPIO_InitStructure);


? ? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

? ? GPIO_Init(GPIOB, &GPIO_InitStructure);


? ? I2C_InitTSturcture.I2C_ClockSpeed = bound;

? ? I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;

? ? I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;

? ? I2C_InitTSturcture.I2C_OwnAddress1 = address;

? ? I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;

? ? I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

? ? I2C_Init(I2C2, &I2C_InitTSturcture);


? ? I2C_Cmd(I2C2, ENABLE);

}

u8 iic_err_count(void)

{

? ? static u8 err_count = 0;

? ? err_count++;

? ? vTaskDelay(1);

? ??

? ? if (err_count > 10)

? ? {

err_count = 0;

? ? ? ? return 1;

? ? }

? ? return 0;

}

/**

?* @brief 讀取數(shù)據(jù)

?*?

?* @param addr 設(shè)備地址

?* @param reg 寄存器地址

?* @return u8?

?*/

u8 IIC_ReadBuffer(u8 addr, u8 reg, u8 *buf, size_t len)

{

? ? static u8 ret = 1;


? ? if (len == 0 || ret != 1)

? ? {

? ? ? ? if (ret == 0)

? ? ? ? {

? ? ? ? ? ? printf("len error\r\n");

? ? ? ? ? ? ret = 2;

? ? ? ? }

? ? ? ? return 1;

? ? }

? ? if (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY) != RESET)

? ? {

? ? ? ? printf("bus busy\r\n");

? ? ? ? ret = 0;

? ? ? ? return 1;

? ? }


? ? I2C_GenerateSTART(I2C2, ENABLE); // 開始信號


? ? while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))

? ? {

? ? ? ? if (iic_err_count())

? ? ? ? {

? ? ? ? ? ? printf("not com\r\n");

? ? ? ? ? ? return 1;

? ? ? ? }

? ? }

? ? I2C_Send7bitAddress(I2C2, addr<<1, I2C_Direction_Transmitter); // 發(fā)送設(shè)備地址


? ? while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

? ? {

? ? ? ? if (iic_err_count())

? ? ? ? {

? ? ? ? ? ? printf("not com1\r\n");

? ? ? ? ? ? return 1;

? ? ? ? }

? ? }


? ? I2C_SendData(I2C2, (u8)(reg & 0x00FF));? // 發(fā)送要讀取的寄存器地址

? ? while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

? ? {

? ? ? ? if (iic_err_count())

? ? ? ? {

? ? ? ? ? ? printf("not com2\r\n");

? ? ? ? ? ? return 1;

? ? ? ? }

? ? }

? ? I2C_GenerateSTART(I2C2, ENABLE); // 開始信號


? ? while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))

? ? {

? ? ? ? if (iic_err_count())

? ? ? ? {

? ? ? ? ? ? printf("not com3\r\n");

? ? ? ? ? ? return 1;

? ? ? ? }

? ? }

? ? I2C_Send7bitAddress(I2C2, addr<<1, I2C_Direction_Receiver); // 發(fā)送設(shè)備地址


? ? while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

? ? {

? ? ? ? if (iic_err_count())

? ? ? ? {

? ? ? ? ? ? printf("not com4\r\n");

? ? ? ? ? ? return 1;

? ? ? ? }

? ??

? ? }

? ? for (size_t i = 0; i < len; i++)

? ? {

? ? ? ? while(I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE) == RESET)

? ? ? ? {

? ? ? ? ? ? I2C_AcknowledgeConfig(I2C2, DISABLE); // 關(guān)閉應(yīng)答

? ? ? ? }

? ? ? ? buf[i] = I2C_ReceiveData(I2C2); // 讀取數(shù)據(jù)

? ? }


? ? I2C_GenerateSTOP(I2C2, ENABLE); // 停止信號

? ? return 0;

}


image.pnglog如圖


使用gpio翻轉(zhuǎn)實驗過,PB10和PB11是可以正常翻轉(zhuǎn)的


把外設(shè)去掉只接示波器發(fā)現(xiàn)也沒時鐘和數(shù)據(jù)信號


先確定硬件是否加上拉電阻。然后能抓到主機發(fā)送的START信號吧,數(shù)據(jù)線在時鐘線高電平時拉低,然后抓到了主機發(fā)送的地址信息了嗎。這種情況往往是從設(shè)備沒有ack信號導(dǎo)致總線卡死,出現(xiàn)卡死時,加上超時檢測,然后停止STOP IIC,重現(xiàn)開始一次START。


沒有開始信號,時鐘和數(shù)據(jù)都是低電平,我找硬件確認(rèn)下有沒有上拉電阻,如果沒有的話可以配置成內(nèi)部上拉嗎


引腳必須配置成服用開漏輸出,不能再配置內(nèi)部上拉了,所以必須外部加上拉電阻,4.7K左右就行。


只有登錄才能回復(fù),可以選擇微信賬號登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频