GD32替换STM32移植过程
1. 硬件芯片移植下面以 GD32F103RET6 替换 STM32F103RET6为例
硬件上使用对应的GD32芯片替换STM32,如使用 GD32F103RET6 替换 STM32F103RET6,其引脚数与引脚定义都是一样的
到兆易创新官网 - 资料下载 - 对应系列芯片 - 应用软件 - 找到GD32F1x0_Addon_V3.1.0.rar,解压安装
3. 更换算法文件(.FLM)到Keil 的Flash文件夹中(Keil_v5\ARM\Flash)
资源下载:GD32F10xxx Keil IDE Config.rar 2. 软件配置
2.1 修改外部晶振起振超时时间
不用外部晶振可跳过此步 由于GD芯片与ST芯片的启动时间存在差异,需要对下面参数进行修改
搜索以下代码
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)
修改为:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)
2.2 增加DMA功能
下面以串口3为例
GD32替换STM32的最大问题就是串口收发问题,经常出现丢数据异常,使用DMA处理串口数据,可有效解决该问题。 串口3与DMA初始化函数
#define USE_USART3_DMA_RX 1
char Usart3data;
u8 Usart3flag =0;
u8 usart3Count=0;
void USART3_Configuration(u32 BaudRate)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStruct;
//打开usart3要使用的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
//配置串口TX作为推挽复用端口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置串口RX作为浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//一个抢占优先级,3个从优先级
NVIC_InitStructure.NVIC_IRQChannel =USART3_IRQn; //和库函数手册不一样
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //主优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_Init(&NVIC_InitStructure);
//配置USART
USART_InitStructure.USART_BaudRate = BaudRate; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶校验
USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //模式
USART_Init(USART3, &USART_InitStructure); //写入结构体
// USART_Cmd(USART3, ENABLE);//使能usart3
USART_ITConfig(USART3,USART_IT_PE,ENABLE);
USART_ITConfig(USART3, USART_IT_RXNE,ENABLE); //打开usart3的接收中断
USART_ClearFlag(USART3,USART_IT_RXNE); //清除中断标志
// USART_ClearFlag(USART3, USART_FLAG_TC); // 清标志
/********************************以下是对DMA的参数初始化**********************************/
#if USE_USART3_DMA_RX
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 开启串口3空闲中断
DMA_DeInit(DMA1_Channel3);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// DMA1时钟初始化
// RX DMA1 ??5
DMA_InitStruct.DMA_BufferSize = sizeof(Usart3data); // 传输的数据大小
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; // 外设作为数据的来源
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; // 不使能M TO M传输
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)Usart3data; // 设置DMA源地址:串口数据寄存器
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存数据单元
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; // 外设地址不增
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; // DMA模式一次或者循环模式
//DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // DMA模式一次或者循环模式
DMA_InitStruct.DMA_PeripheralBaseAddr = USART3_BASE + 0x04; // 设置DMA源地址:串口数据寄存器地址
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据单元
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不增加
DMA_InitStruct.DMA_Priority = DMA_Priority_High; // 优先级为中
// 配置DMA通道
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// 清除DMA所有标志
DMA_ClearFlag(DMA1_FLAG_TC3);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TE,ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);//开启串口DMA接收
DMA_Cmd(DMA1_Channel3, ENABLE); // 使能DMA通道
#else
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启串口接收中断
#endif
// USART_ClearFlag(USART3, USART_FLAG_TC); /* 清除标志避免第一个字符丢失 */ // 使用GD32时,发送第一个数据前不要清除 USART_FLAG_TC(发送完成标志位)
USART_Cmd(USART3, ENABLE); //使能串口
}
串口3中断服务函数
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if USE_USART3_DMA_RX
if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)//接收中断(接收到的数据必须是0x0d 0x0a结尾) 读取接收中断标志位后自动清零接收中断标志位
{
Receice_DataPack(3);
Res = USART3->SR;
Res = USART3->DR;
}
#else
#endif
}
#define USART_RX_BUFF_SIZE 200
void Receice_DataPack(uint8_t channel)
{
//接收到的数据长度
uint32_t buff_length;
u32 i;
static uint8_t byteindex = 0;
switch(channel)
{
case 3:
{
//获取这一帧数据个数
buff_length = USART_RX_BUFF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);
for(;byteindex < buff_length;byteindex++)
{
Putch(USART3,Usart3data);
}//回显处理
byteindex = buff_length;
if(Usart3data == '\r' ||Usart3data == '\n') //接收到了一帧完整的命令
{
Usart3flag = 1;//接收到空行的命令
Putch(USART3,'\n');//MAC下不发送新行会覆盖输入
byteindex = 0;
if(Usart3data == '\n' || Usart3data == '\r')//去掉接受数据中尾部的回车换行符
{
Usart3data = 0;
}
if(Usart3data == '\r')
{
Usart3data = 0;
}
return;
}
if(buff_length >= 50)
{
byteindex = 0;
DMA1_Channel3->CCR&=~(1<<0); //关闭DMA接受中断
DMA1_Channel3->CNDTR=USART_RX_BUFF_SIZE;//清空DMA数据计数器,重新计数下一帧数据
DMA1_Channel3->CCR|=1<<0;
}
break;
}
default: break;
}
}
voidPutch(USART_TypeDef* USARTx,u8 k) // 回显函数
{
if(k == '\n')
{
USART_SendData(USARTx,'\r');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
USART_SendData(USARTx,'\n');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
}
else if(k == '\b')//接收到
{
USART_SendData(USARTx,'\b');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
USART_SendData(USARTx,' ');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
USART_SendData(USARTx,'\b');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
}
else
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待发送结束
USART_SendData(USARTx,k);
//while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
}
main函数
int main()
{
... //省略代码
while(1)
{
... //省略代码
if(Usart3flag==1) //接收完成
{
port_Index=3;
CheckUartCmd(Usart3data);
Usart3flag=0;
memset(Usart3data,'\0',sizeof(Usart3data));//清空接收缓冲区
DMA1_Channel3->CCR&=~(1<<0); //关闭DMA接受中断
DMA1_Channel3->CNDTR=sizeof(Usart3data);//清空DMA数据计数器,重新计数下一帧数据
DMA1_Channel3->CCR|=1<<0;
usart3Count=0;
}
}
}
慢醇 发表于 2022-1-25 15:17
由于GD芯片与ST芯片的启动时间存在差异,需要对下面参数进行修改
请教外部晶振起振超时时间起什么作用?如果我把超时时间都设置成0XFFFF在ST芯片下运行有没有什么问题,如果没问题那就可以替代了 ST的HSE_STARTUP_TIMEOUT这个参数是0x0500,如果我把它设成0XFFFF有没有问题呢?我看了下用到这个参数的函数以下这几个:RCC_WaitForHSEStartUp(void),SetSysClockToHSE(void),void SetSysClockTo24(void),void SetSysClockTo36(void)....我查了下我只用到RCC_WaitForHSEStartUp(void)这个函数,判断外部时钟是否正常,不正常则启用内部时钟。而看了这个函数把HSE_STARTUP_TIMEOUT设大好象没问题,最多就是如果外部时钟故障等待时间长了点而已,请问还有其它问题吗?附上这个函数。
ErrorStatus RCC_WaitForHSEStartUp(void)
{
__IO uint32_t StartUpCounter = 0;
ErrorStatus status = ERROR;
FlagStatus HSEStatus = RESET;
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);
StartUpCounter++;
} while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));
if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET)
{
status = SUCCESS;
}
else
{
status = ERROR;
}
return (status);
} 请问楼主我用的是STM32F103VBT6这个芯片,如果用GD32F103VBT6替换,除了要改变HSE_STARTUP_TIMEOUT这个参数外,还有没有其它问题,我是想直接用原来ST的程序,把这个参数都改成0XFFFF,两种芯片都用同一个程序,这样行不行,我用到串口,定时器的比较功能,PVD,FLASH,ADC,谢谢指教! gd32f103用stm32的库使用usb的时候需要修改哪些代码 8MHZ晶振变成12MHZ可不可以把主频变成108 GD32系列兼容STM32一系列吗? gd32f130对应哪一块stm32 stm32生成的程序能直接烧录在gd32上吗 GD32F130C8真的可以兼容ST的吗 可以替代兼容STM32的吗 硬件I2C 到底是不是个坑 GD32F103VBT6支持FSMC功能吗?
页:
[1]
2