国产芯片--GD32VW553-IOT UART的外设使用
分享作者:genius_nn
评测品牌:萤火工场
评测型号:GD32VW553-IOT
发布时间:2025-04-02 11:53:38
0
前言
本来是想提交一个mpu6050读取数据的代码的,但是根据测试历程写的代码不知道在哪里出了问题,先交一个串口发送数据到上位机的代码,交个作业。我把I2C相关代码贴在最后,想请各位大佬帮我看看是什么原因。
开源口碑分享内容

在使用UART0时如果只有以一个USB-TTL模块,也可以使用该引脚下载代码到芯片,USB-TTL的RXD接在PB15,TXD接在PA8即可。

本代码实现的是一个LED灯珠,100ms闪烁一次,串口200ms向上位机发送一次测试信息的代码。




#include "gd32vw55x.h"
#include "gd32vw553h_eval.h"
#include "systick.h"
#include <stdio.h>
#include "myI2C.h"

void com_usart_init(void);
void led_init(void);


int main(void)
{
	systick_config();
    led_init();
	// initialize the COM
	com_usart_init();

//  i2c_config();
    /* configure I2C */
//	MPU6050_Init();
//	MPU6050_GetID();
//	printf("mpu6050ID: %X \r\n",mpu6050ID);
    int i = 0;
    while(1)
    {
    	gpio_bit_set(GPIOA, GPIO_PIN_1);
    	delay_1ms(100);
    	gpio_bit_reset(GPIOA, GPIO_PIN_1);
    	delay_1ms(100);
    	printf("uart transmit test times: %d !\n\r",i++);
    }
}

void led_init(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
	gpio_bit_reset(GPIOA, GPIO_PIN_1);
}

void com_usart_init(void)
{
    
    rcu_periph_clock_enable(RCU_GPIOB);     //开启GPIOB时钟
    rcu_periph_clock_enable(RCU_GPIOA);     //开启GPIOA时钟
    rcu_periph_clock_enable(RCU_USART0);    //开启USART0时钟

    gpio_af_set(GPIOB, GPIO_AF_8, GPIO_PIN_15); //将PB15复用到USART0_TX
    /* connect port to USART RX */
    gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_8);  //将PA8复用到USART0_RX

    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_15);  //配置PB15为复用推挽输出
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_15);  //配置PB15速度25MHz

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);   //配置PA8为复用推挽输入
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_8);   //配置PA8速度25MHz

    usart_deinit(USART0);   //USART0复位
    usart_word_length_set(USART0, USART_WL_8BIT);   //数据位长度8位
    usart_stop_bit_set(USART0, USART_STB_1BIT);     //停止位1位
    usart_parity_config(USART0, USART_PM_NONE);     //无校验位
    usart_baudrate_set(USART0, 115200U);            //波特率115200
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);     //接收使能
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);   //发送使能

    usart_enable(USART0);                           //USART0使能
}



下面就是硬件I2C0外设在初始化和通信时的相关代码,我是根据   测试历程中的AT24Cxx的代码   改写的,但是在读取MPU6050寄存器数据的时候,无法完成数据传输方向的改变(主机从发送数据改为主机从mpu6050寄存器读取数据),导致后面读取数据相关的代码接连超时。

#include "myI2C.h"
#include "mpu6050_reg.h"

uint8_t mpu6050ID = 0x00;

void i2c_gpio_config(void)
{
	/* enable GPIOA clock */
	rcu_periph_clock_enable(RCU_GPIOA);
	/* enable I2C0 clock */
	rcu_periph_clock_enable(RCU_I2C0);
	/* connect PA2 to I2C0_SCL */
	gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_2);
	/* connect PA3 to I2C0_SDA */
	gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_3);
	/* configure GPIO pins of I2C0 */
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, GPIO_PIN_2);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, GPIO_PIN_3);
    printf("i2c_gpio_config ok!\n\r");
}

void i2c_config(void)
{
	i2c_gpio_config();
//    i2c_timing_config(I2C0, 0x0, 0x8, 0);
//    i2c_master_clock_config(I2C0, 0x30, 0x91);	//约为400KHz 频率 (APB1 总线80Mhz/((4~6个I2CCLK时钟周期)+(sclL+1)*(sclH+1)*(PSC+1)))
	i2c_timing_config(I2C0, 0x02, 0x08, 0);
	i2c_master_clock_config(I2C0, 0xC6, 0xC7);	//50KHz

//    i2c_address_config(I2C0, I2C_OWN_ADDRESS7, I2C_ADDFORMAT_7BITS);

    i2c_enable(I2C0);
    printf("i2c_config ok!\n\r");
}



//向mpu6050寄存器写入一字节数据
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	int i;
	uint8_t buff[2]={RegAddress,Data};
	//发送从机设备地址,且是写入方向
	i2c_master_addressing(I2C0, MPU6050_SENSOR_ADDR, I2C_MASTER_TRANSMIT);
	i2c_transfer_byte_number_config(I2CX, 1);
	// 发送起始信号
	i2c_start_on_bus(I2C0);
	/* wait until the transmit data buffer is empty */
	I2C_STAT(I2C0) |= I2C_STAT_TBE;
	while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
	for(i = 0; i < 2; i++)
	{
		i2c_data_transmit(I2C0, buff[i]);
	}
	i2c_stop_on_bus(I2C0);
	/* wait until stop condition generate */
	while(!i2c_flag_get(I2C0, I2C_FLAG_STPDET));
	/* clear the STPDET bit */
	i2c_flag_clear(I2C0, I2C_FLAG_STPDET);
}

//使用i2c读取mpu6050寄存器数据
//p_buffer:存放读取数据的缓存区,read_address:寄存器地址,number_of_byte:读取字节数
void MPU6050_ReadReg(uint8_t *p_buffer, uint8_t read_address, uint16_t number_of_byte)
{
    static uint32_t timeout = 0;
    uint16_t bytes_left = number_of_byte;
    /* wait until the transmit data buffer is empty */
    I2C_STAT(I2C0) |= I2C_STAT_TBE;
    //发送从机设备地址,且是写入方向
    i2c_master_addressing(I2C0, MPU6050_SENSOR_ADDR, I2C_MASTER_TRANSMIT);
    /* configure number of bytes to be transferred */
    i2c_transfer_byte_number_config(I2CX, 1);
    i2c_automatic_end_disable(I2CX);
    /* i2c master sends start signal only when the bus is idle */
    while(i2c_flag_get(I2CX, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) 
    {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT) 
    {
        i2c_start_on_bus(I2CX);
        timeout = 0;
    } 
    else
    {
        printf("I2C bus is busy!\n\r");
    	timeout = 0;
    }
     /* wait until the transmit data buffer is empty */
    while((!i2c_flag_get(I2CX, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) 
    {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT)
    {
        i2c_data_transmit(I2C0, read_address);
        timeout = 0;
    }
    else
    {
        printf("I2C transmit data error!\n\r");
		timeout = 0;
    }
    /* wait until the transmit data buffer is empty */
    while((!i2c_flag_get(I2CX, I2C_FLAG_TC)) && (timeout < I2C_TIME_OUT)) 
    {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT) 
    {
        //发送从机设备地址,且是读取方向
        i2c_master_addressing(I2CX, MPU6050_SENSOR_ADDR, I2C_MASTER_RECEIVE);
        /* enable I2C reload mode */
        i2c_reload_enable(I2CX);
        timeout = 0;
    }
    else
    {
    	printf("I2C reload error!\n\r");
    	timeout = 0;
    }
    /* wait for TCR flag */
    while((!i2c_flag_get(I2CX, I2C_FLAG_TCR)) && (timeout < I2C_TIME_OUT)) {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT)
    {
        //configure the number of bytes to be received
        i2c_transfer_byte_number_config(I2CX, number_of_byte);
        i2c_reload_disable(I2CX);
        /* enable I2C automatic end mode in master mode */
        i2c_automatic_end_enable(I2CX);
        timeout = 0;
    }
    else
    {
        printf("I2C reload config error!\n\r");
		timeout = 0;
    }
     /* wait until TBE bit is set */
    while((!i2c_flag_get(I2CX, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT) 
    {
        while(bytes_left) 
        {
        	if(i2c_flag_get(I2CX, I2C_FLAG_RBNE))
        	{
				*p_buffer = i2c_data_receive(I2CX);
				p_buffer++;
				bytes_left--;
        	}
        }
        timeout = 0;
    }
    else
    {
        printf("I2C receive data error!\n\r");
    	timeout = 0;
    }
    i2c_stop_on_bus(I2C0); //发送停止信号
    /* wait until stop condition generate */
    while(!i2c_flag_get(I2C0, I2C_FLAG_STPDET));
    /* clear the STPDET bit */
    i2c_flag_clear(I2C0, I2C_FLAG_STPDET);

}

void MPU6050_Init(void)
{
//	/*MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器*/
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);				//电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);				//电源管理寄存器2,保持默认值0,所有轴均不待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);				//采样率分频寄存器,配置采样率
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);					//配置寄存器,配置DLPF
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);			//陀螺仪配置寄存器,选择满量程为±2000°/s
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);			//加速度计配置寄存器,选择满量程为±16g
	printf("mpu6050 init OK !\n\r");
}


#ifndef _MYI2C_H_
#define _MYI2C_H_

#include "gd32vw55x.h"
#include "gd32vw553h_eval.h"

#define I2C_TIME_OUT   (uint32_t)(20000)
#define I2CX		   	I2C0

typedef enum
{
    I2C_START = 0,
    I2C_SEND_ADDRESS,
    I2C_RESTART,
    I2C_TRANSMIT_DATA,
    I2C_RELOAD,
    I2C_STOP,
    I2C_END
}i2c_process_enum;

extern uint8_t mpu6050ID;

void MPU6050_Init(void);
void MPU6050_GetID(void);
void MPU6050_ReadReg(uint8_t *p_buffer, uint8_t read_address, uint16_t number_of_byte);
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
void i2c_config(void);

#endif /* _MYI2C_H_ */





全部评论
暂无评论
0/144