APM/Air32F103/CH32F203/STM32F103程序互通说明
✨感觉国内中低端芯片就像 春秋时期,各诸侯群雄纷争的局面。各厂商都推出相关的替代竞品方案。这对于嵌入式开发从业者来说,有更多的开发方案可选。同时开发者不得不面对不同方案,项目移植工作。
- 🎉个人觉得同架构,同内核的芯片百花齐放百家争鸣是一件好事,任何产品方案都有可替代性,才不会被别人掐脖子和一家垄断独大的局面发生。同时保持产品差异化,面对不同应用场景和个性化需求方案。对于共有的功能外设应该建立统一的标准。
- 🔖目前的局面,谁的资料越多越开放,学习的和使用的人就越多,反馈给上层芯片设计制造企业的信息也就越多,这就是一个循环的生态。不要把自己的产品资料搞的神神秘秘的,什么都不对外公布,让学习和使用的人望而却步,这种傲慢的厂商迟早都会被淘汰掉。
🚩 注意:这里只针对通用外设寄存器地址相同的程序的互换性,不包含差异化内容。
- ⚡需要注意一点:APM/Air32F103/CH32F203/STM32F103各自的SDK工程中的有些个别寄存器定义的名称有个别的差异,大部分名称都是一样的。
⛳APM/Air32F103/CH32F203/STM32F103主频说明
- 🌿Air32F103最高216MHz(最高256MHz)6;CH32F203最高144MHz,APM最高96MHz,在通用的主频下,通用外设部分基本通用,只选更换对应的芯片型号。
APM/Air32F103//STM32F103转CH32F203程序
- 🌿例如匹配CH32F203的96MHz或144MHz主频时,需要在定义主频的地方补充96MHz以及144MHz的相关宏定义和时钟初始化函数代码。
-
- 📋以Air32F103为例,在
system_air32f10x.c
中添加如下代码:
- 📋以Air32F103为例,在
- 时钟初始化函数代码
#elif defined SYSCLK_FREQ_96MHz
/*********************************************************************
* @fn SetSysClockTo96_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
}
while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz(HSE=32Mhz)
*/
// RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
// RCC_PLLMULL ) );
// RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12 );
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE | RCC_CFGR_PLLMULL12);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_144MHz
/*********************************************************************
* @fn SetSysClockTo144_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
}
while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* CH32F20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8Mhz)
* CH32F20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz(HSE=32Mhz)
*/
// RCC->CFGR0 &= ( uint32_t )( ( uint32_t )~( RCC_PLLSRC | RCC_PLLXTPRE |
// RCC_PLLMULL ) );
// RCC->CFGR0 |= ( uint32_t )( RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12 );
/* PLL configuration: PLLCLK = HSE * 18 = 144 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE | RCC_CFGR_PLLMULL18);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
🌿STM32F103转CH32F203也是一样。
- 📌具体案例工程可以参考《【WCH】基于STM32标准库程序烧录到CH32F203中运行方法》
- 🌿对于极海的APM32应该也是差不多,这个没有具体去使用SDK工程验证。
📓CH32F203转APM/Air32F103//STM32F103
- 🌿反过来使用也就是调整对应的主频。
- 🌿对于操作
PC
端口存在差异,具体看下面的内容。
🎯APM/Air32F103//STM32F103转CH32F203程序GPIO端口差异
- 🎈可以参考相关篇《【WCH】基于Keil环境CH32F203 GPIO点灯实验》
- 📗CH32F203芯片的
PC
端口上的引脚都需要右移13位才可以。其他端口引脚不需要,具体操作可以打开CH32F203查看相关SDK工程demo
案例,也可以去翻阅上面的相关参考篇内容里做了使用说明。
⛳烧录工具差异
- 🚩针对SWD下载的话,它们之间的烧录工具没有通用的统一的,都存在一定的差异。个别的可以相互直接烧录使用,没有一款通用的,网上有售卖兼容通用的烧录器,具体的没有购买测试过。
- 🌿目前合宙AIR32F103CBT6的DAP-LIN固件(最新的V2版本支持)可以烧录自家的和STM32的,其他家的没有做具体的测试,但是不支持WCH的CH32F203的。
- 🔖相关篇《合宙AIR32F103CBT6刷回CMSIS-DAP固件和DAP升级固件以及刷ST-LINK V2-1固件方法》
- 🌿WCH的WCH-DAPLink(CH549G版本)值针对自家的使用,不兼容其他家的,其他家的也不支持他家的。烧录配置:
- 🍁不管是烧录到哪一家的同型号芯片里面,都需要配置各自的FLM文件。
📓程序烧录差异
- 🔖具体各型号的烧录器支持情况,需要根据各自芯片厂商相关烧录资料说明。
- ✨目前手上使用的芯片情况来看,APM的支持ST-LINKV2,但是不支持合宙的DAP-LINKV2。CH32只能用他们自家的DAP-LINK工具下载。STM32支持合宙的DAP-LINKV2。