国产芯片--GD32VW553-IOT UART的外设使用
分享作者:genius_nn
评测品牌:萤火工场
评测型号:GD32VW553-IOT
发布时间:2025-04-02 11:53:38
1 0
前言
开源口碑分享内容
在使用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