gd32 gpio总线复用两种不同功能会相互影响吗
时间: 2023-09-08 07:03:07 浏览: 285
在GD32片上系统中,GPIO总线复用可以将一个GPIO引脚与多个不同功能功能模块相连,例如串口、I2C、SPI等。不同功能模块对于GPIO的复用是通过设置相应的寄存器来实现的。
当一个GPIO引脚被多个模块复用时,不同功能模块使用GPIO引脚的寄存器配置可能会相互影响。例如,一个引脚被配置为串口传输数据时,对应的寄存器会设置为串口传输的模式,那么此时如果另外一个功能模块要使用同一个引脚,就需要先关闭串口模块并修改相应寄存器的配置。
因此,在GD32芯片中,如果多个不同功能模块需要复用同一个GPIO引脚,就需要通过软件控制来解决冲突。一般来说,我们可以通过以下几个步骤来实现复用控制:
1. 在使用一个功能模块之前,关闭其他可能会影响该引脚的功能模块。
2. 配置需要使用的功能模块的相关寄存器,使其与该引脚相匹配。
3. 在使用完该功能模块后,恢复之前关闭的功能模块的配置。
4. 避免不同功能模块同时使用引脚,以免造成冲突和不可预测的结果。
总之,虽然GD32 GPIO总线的复用可以实现一个GPIO引脚的多功能化使用,但是在配置复用功能时需要仔细考虑不同模块之间的互相影响,并通过软件控制来避免冲突。
相关问题
作为一个资深嵌入式工程师,编写基于GD32C103单片机,采集LVDT传感器电压,进而转换为位移量,通过CAN总线输出的代码
以下是一个简单的基于GD32C103单片机采集LVDT传感器电压、转换为位移量并通过CAN总线输出的代码框架,供参考:
```c
#include "gd32f10x.h"
#include "can.h"
#define LVDT_ADC_CHANNEL ADC_CH_0
#define LVDT_ADC_GPIO_PORT GPIOA
#define LVDT_ADC_GPIO_PIN GPIO_PIN_0
#define VREF 3300 // 单位:mV
#define LVDT_SENSITIVITY 1 // LVDT传感器灵敏度,单位:mV/mm
// 初始化ADC
void adc_init(void)
{
/* 使能GPIOA时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* 使能ADC时钟 */
rcu_periph_clock_enable(RCU_ADC);
/* 配置PA0为模拟输入引脚 */
gpio_mode_set(LVDT_ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, LVDT_ADC_GPIO_PIN);
/* 配置ADC时钟分频和工作模式 */
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
adc_mode_config(ADC_MODE_FREE);
/* 配置ADC通道为PA0 */
adc_channel_config(LVDT_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5);
/* 使能ADC */
adc_enable();
/* 校准ADC */
adc_calibration_enable();
}
// 采样LVDT电压并返回对应的位移量,单位:mm
float lvdt_volt_to_disp(void)
{
uint16_t adc_value;
float voltage, displacement;
/* 配置ADC采样模式为单次转换 */
adc_special_function_config(ADC_SCAN_MODE, DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, DISABLE);
adc_special_function_config(ADC_DISCONTINUOUS_MODE, DISABLE);
adc_special_function_config(ADC_DATA_ALIGN_RIGHT, ENABLE);
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
/* 开始ADC转换 */
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
/* 等待转换完成 */
while(SET != adc_flag_get(ADC_FLAG_EOC));
/* 读取ADC转换值 */
adc_value = adc_regular_data_read();
/* 计算对应的电压值 */
voltage = (float)adc_value * VREF / 4096;
/* 计算对应的位移量 */
displacement = voltage / LVDT_SENSITIVITY;
return displacement;
}
// 初始化CAN总线
void can_init(void)
{
/* 使能GPIOB时钟 */
rcu_periph_clock_enable(RCU_GPIOB);
/* 使能CAN时钟 */
rcu_periph_clock_enable(RCU_CAN0);
/* 配置PB8和PB9为复用功能 */
gpio_mode_set(GPIOB, GPIO_MODE_AF_PP, GPIO_PUPD_PULLUP, GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF_PP, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_9);
/* 配置CAN总线 */
can_deinit(CAN0);
can_struct_para_init(CAN_INIT_STRUCT, CAN_TTCM_Mode, DISABLE, CAN_ABOM_State, DISABLE,
CAN_AWUM_State, DISABLE, CAN_NART_State, ENABLE, CAN_RFLM_State, DISABLE,
CAN_TXFP_State, DISABLE, CAN_Mode, CAN_NORMAL_MODE, CAN_SJW, CAN_SJW_1TQ,
CAN_BS1, CAN_BS1_5TQ, CAN_BS2, CAN_BS2_2TQ, 6);
can_init(CAN0, &CAN_INIT_STRUCT);
}
// 发送位移量数据到CAN总线
void send_disp_via_can(float disp)
{
uint8_t data[8];
uint32_t mailbox;
/* 将位移量转换为CAN数据格式 */
int16_t disp_data = (int16_t)(disp * 10);
data[0] = disp_data >> 8;
data[1] = disp_data & 0xFF;
/* 发送数据到CAN总线 */
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, 0, CAN_TX_DATA_FRAME, CAN_STANDARD_ID, 0);
CAN_TX_MESSAGE_STRUCT.tx_sfid = 0x123;
CAN_TX_MESSAGE_STRUCT.tx_dlen = 2;
CAN_TX_MESSAGE_STRUCT.tx_data[0] = data[0];
CAN_TX_MESSAGE_STRUCT.tx_data[1] = data[1];
can_message_transmit(CAN0, &CAN_TX_MESSAGE_STRUCT);
}
int main(void)
{
float lvdt_disp;
/* 初始化ADC和CAN总线 */
adc_init();
can_init();
while(1)
{
/* 采样LVDT电压并计算位移量 */
lvdt_disp = lvdt_volt_to_disp();
/* 发送位移量数据到CAN总线 */
send_disp_via_can(lvdt_disp);
}
}
```
需要注意的是,上述代码仅供参考,具体实现还需要根据具体硬件平台和实际应用场景进行适当修改和优化。
gd32 spi1 代码
GD32系列微控制器中的SPI1(Serial Peripheral Interface)是一种全双工通信总线,常用于串行通信如I2C、SPI等。以下是一个基本的GD32F10x系列MCU使用SPI1发送数据的例子代码片段:
```c
#include "gd32f10x.h" // 包含GD32的头文件
void SPI1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // 启动GPIOA和GPIOB时钟
GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE); // 设置GPIO复用映射到SPI1
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 波特率预分频设置
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // 数据位数设置为8位
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High; // 主从机极性设置为主
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // 采样相位设置为上升沿
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; // 首位模式设置为MSB(高位先发)
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // 模式设置为主模式
SPI1_Init(&SPI_InitStruct); // 初始化SPI1
SPI1_Cmd(ENABLE); // 启动SPI1模块
}
void SPI1_SendData(uint8_t data)
{
SPI1_SendDataBlocking(data); // 使用阻塞模式发送数据
}
int main(void)
{
// 其他初始化...
SPI1_Init(); // 初始化SPI1
uint8_t tx_data = 0x5A; // 待发送的数据
SPI1_SendData(tx_data); // 发送数据
while (1) {}
return 0;
}
```
阅读全文