GD32F4xx与STM32F4xx外设驱动开发实战解析
本文基于实际项目代码,详细解析GD32F4xx与STM32F4xx系列微控制器的常用外设驱动开发方法,涵盖SysTick定时器、USART通信、DMA传输及RTC实时时钟等核心模块,并对比两者在代码实现上的异同。
一、SysTick系统定时器:精准延时与时间戳
1. 功能概述
SysTick是Cortex-M系列内核的24位系统定时器,常用于实现精准延时和系统时间基准。代码中通过配置SysTick中断频率为1MHz(每微秒一次),实现微秒级延时。
2. 关键代码分析
c
Copy
// systick.c
void systick_config(void) {
if (SysTick_Config(SystemCoreClock / 1000000U)) { // 1MHz
while(1); // 配置失败则死循环
}
NVIC_SetPriority(SysTick_IRQn, 0x00U); // 最高中断优先级
}
void delay_1us(uint32_t count) {
delay = count;
while (delay != 0); // 忙等待
}
// 中断中递减计数器
void delay_decrement(void) {
tick++;
if (delay != 0) delay--;
}
3. 注意事项
- 忙等待问题:
delay_1us
通过循环占用CPU实现延时,高精度但效率低。优化方向:结合RTOS的任务调度或中断驱动。 - 时间戳功能:
tick
变量记录系统启动后的微秒数,可用于性能分析或定时任务触发。
二、USART通信:实现数据收发
1. 初始化与回调
代码通过Usart0_init()
初始化串口,并注册接收回调函数Usart0_on_recv
,实现数据接收后自动打印。
c
Copy
// main.c
void Usart0_on_recv(uint8_t* data, uint32_t len) {
printf("recv: %s %d\r\n", data, len);
}
int main() {
systick_config();
Usart0_init();
while(1) {
Usart0_send_byte(cnt++); // 发送数据测试
delay_1ms(1000);
}
}
2. 跨平台差异
- GD32:使用
gd32f4xx_usart.h
中的API,如usart_interrupt_enable
。 - STM32:依赖
stm32f4xx_usart.h
,函数命名类似但前缀不同(如USART_SendData
)。
三、DMA传输:内存高效搬运
1. 配置流程
代码通过DMA2的Stream0实现内存到内存的数据搬运,适合大块数据快速传输。
c
Copy
// DMA配置示例
void DMA_config() {
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_InitTypeDef param = {
.DMA_DIR = DMA_DIR_MemoryToMemory,
.DMA_PeripheralBaseAddr = (uint32_t)src,
.DMA_Memory0BaseAddr = (uint32_t)dst,
.DMA_BufferSize = 5,
// 其他参数省略...
};
DMA_Init(DMA2_Stream0, ¶m);
DMA_Cmd(DMA2_Stream0, ENABLE);
}
2. 应用场景
- 数据传输不占用CPU,适合高速ADC采集、摄像头数据传输等场景。
四、RTC实时时钟:精准时间管理
1. BCD编码转换
RTC模块通常以BCD格式存储时间,代码通过宏实现十进制与BCD互转:
c
Copy
#define WRITE_BCD(val) ((val / 10) << 4) + (val % 10)
#define READ_BCD(val) (val >> 4) * 10 + (val & 0x0F)
2. 初始化与读取
c
Copy
void RTC_config() {
pmu_backup_write_enable(); // 启用备份域
rcu_osci_on(RCU_LXTAL); // 开启外部低速晶振
rtc_parameter_struct rps = {
.year = WRITE_BCD(23), .month = WRITE_BCD(4),
.hour = WRITE_BCD(12), // 其他参数省略...
};
rtc_init(&rps);
}
void RTC_read() {
rtc_current_time_get(&rps);
uint8_t hour = READ_BCD(rps.hour);
// 打印时间...
}
五、GD32与STM32代码移植注意事项
- 头文件差异:
- GD32:
gd32f4xx.h
、gd32f4xx_rcu.h
- STM32:
stm32f4xx.h
、stm32f4xx_rcc.h
- GD32:
- 函数命名:
- 时钟控制:GD32的
rcu_periph_clock_enable()
对应STM32的RCC_AHB1PeriphClockCmd()
。
- 时钟控制:GD32的
- 外设寄存器:部分外设地址或位定义不同,需参考各自的数据手册。
六、总结
本文通过代码实例详细解析了GD32/STM32的常用外设驱动开发,涵盖SysTick延时、USART通信、DMA传输及RTC配置。开发时需注意不同芯片的库函数差异,合理选择同步/异步处理方式以提高系统效率。