也给一个简单的例子
#include "at32f403a_407.h"
void I2C_Config(void) {
gpio_init_type gpio_init_struct;
i2c_init_type i2c_init_struct;
// 使能GPIO和I2C时钟
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_I2C1);
// 配置PB6(SCL)、PB7(SDA)为复用开漏
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init_struct.gpio_size = GPIO_SIZE_50MHZ;
gpio_init(GPIOB, &gpio_init_struct);
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_4); // I2C1_SCL
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_4); // I2C1_SDA
// 初始化I2C
i2c_init_struct.i2c_clock_speed = 100000; // 100kHz
i2c_init_struct.i2c_address_mode = I2C_ADDRESS_MODE_7BIT;
i2c_init_struct.i2c_ack_enable = I2C_ACK_ENABLE;
i2c_init(I2C1, &i2c_init_struct);
i2c_enable(I2C1, TRUE);
}
// 读取从设备数据
uint8_t I2C_ReadByte(uint8_t devAddr, uint8_t regAddr) {
uint8_t data;
// 发送起始信号和设备写地址
while(i2c_flag_get(I2C1, I2C_FLAG_BUSY));
i2c_start_on_bus(I2C1);
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
i2c_data_transmit(I2C1, devAddr << 1); // 写地址
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND);
// 发送寄存器地址
i2c_data_transmit(I2C1, regAddr);
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
// 重复起始信号和设备读地址
i2c_start_on_bus(I2C1);
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
i2c_data_transmit(I2C1, (devAddr << 1) | 0x01); // 读地址
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND);
i2c_ack_config(I2C1, I2C_ACK_DISABLE); // 最后一字节无应答
// 读取数据
while(!i2c_flag_get(I2C1, I2C_FLAG_RBNE));
data = i2c_data_receive(I2C1);
// 发送停止信号
i2c_stop_on_bus(I2C1);
while(i2c_flag_get(I2C1, I2C_FLAG_STOPF));
i2c_ack_config(I2C1, I2C_ACK_ENABLE); // 恢复应答
return data;
}
int main(void) {
I2C_Config();
uint8_t val = I2C_ReadByte(0x48, 0x00); // 示例:从地址0x48的0x00寄存器读数据
while(1);
}
|