CW32L012和STM32F103在定位和性能上差异显著,在三角函数的运算性能上的对比亦非常直观。
一、 硬件架构对比(性能基础)
| 芯片型号 | CW32L012C8 | STM32F103C8 |
|---|---|---|
| 内核 | ARM Cortex-M0+ | ARM Cortex-M3 |
| 主频 | 最高 96 MHz | 最高 72 MHz |
| 硬件CORDIC | 支持 | 无 |
| DSP | 无 | 无 |
| 立创样片价格 | 3.69元 | 7.55元 |
两者都没有硬件浮点运算单元。 但在运算三角函数时,CW32L012支持CORDIC算法。
二、 三角运算性能具体分析
1:标准库浮点运算(如 math.h 的 sinf, cosf)
这是最常用但也是最慢的方式。
STM32F103C8:Cortex-M3内核的整体性能,使其在运行相同的软件浮点库时,性能优于CW32L012的Cortex-M0+。
CW32L012C8:Cortex-M0+内核设计更简单,但用软件浮点运算效率较低,耗时会更长。
以下是使用STM32F103C8T6和CW32L012C8T6两种芯片。使用math.h运算SIN和COS的代码实现。
STM32F103使用math.h运算SIN30度与COS30度 :
float angle; void performance_test(unsigned long iterations) { unsigned long i=0; float y1,y2; for(i=1;i<=iterations;i++) { y1=sin(angle); y2=cos(angle); } } void LED_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); } void TIM1_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); TIM_InternalClockConfig(TIM1); TIM_TimeBaseInitTypeDef TIM1_Initstructure; TIM1_Initstructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM1_Initstructure.TIM_CounterMode=TIM_CounterMode_Up; TIM1_Initstructure.TIM_Period=1000-1; //定时时长=72000000/(Prescaler-1)/(Period-1) TIM1_Initstructure.TIM_Prescaler=72-1; TIM1_Initstructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM1,&TIM1_Initstructure); TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); TIM_ClearFlag(TIM1,TIM_IT_Update); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_Initstructure; NVIC_Initstructure.NVIC_IRQChannel=TIM1_UP_IRQn; NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=1; NVIC_Initstructure.NVIC_IRQChannelSubPriority=1; NVIC_Init(&NVIC_Initstructure); TIM_Cmd(TIM1,ENABLE); } unsigned int timecount=0; unsigned int lastcmputetime=0; int main(void) { char temp_buff1[40]; LED_Init(); TIM1_Init(); OLED_Init(); //清屏 OLED_Printf(0,0,OLED_6X8," SIN/COS COMPUTE Test "); OLED_Printf(0,16,OLED_6X8," For 1000000 Times "); OLED_Update(); angle=0.523; //0.785(45度弧度制)=45度/180度*3.14 0.523(30度弧度制)=30/180*3.14 while (1) { sprintf(temp_buff1, " STM32F103 start...... "); OLED_Printf(0, 32, OLED_6X8, temp_buff1); OLED_Printf(0, 48, OLED_8X16, " "); OLED_Update(); timecount=0; performance_test(1000000); lastcmputetime=timecount; sprintf(temp_buff1, " STM32F103 used time: "); OLED_Printf(0, 32, OLED_6X8, temp_buff1); sprintf(temp_buff1, " %d mS ", lastcmputetime); OLED_Printf(0, 48, OLED_8X16, temp_buff1);OLED_Update(); while(1); //由于结果太慢,不进行二次运算,停在这里方便查看时间. 如果需要二次运算,则屏蔽该条语句 timecount=0; while(timecount< 4000); //等待2S } } void TIM1_UP_IRQHandler(void) { static unsigned int flag=0; if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) { TIM_ClearITPendingBit(TIM1,TIM_IT_Update); timecount++; // if(timecount >=500) //以下用于检查时间配置是否准确 // {timecount=0; // flag=1-flag; // if(flag==1) // GPIO_SetBits(GPIOC,GPIO_Pin_13); // else // GPIO_ResetBits(GPIOC,GPIO_Pin_13); // } } }

使用MATH.H执行结果:运算100W次SIN30度与COS30度时间显示内容如下:

CW32L012使用math.h运算SIN30度与COS30度:
核心代码:
void performance_test(unsigned long iterations)
{
unsigned long i=0;
float y1,y2;
CW_FLASH->CR2 = 0x5a5a001B;
for(i=1;i<=iterations;i++)
{
y1=sin(anglef);
y2=cos(anglef);
}
CW_FLASH- >CR2 = 0x5a5a0003;
}

使用MATH.H执行结果:运算100W次SIN30度与COS30度时间显示内容如下:

2:使用硬件CORDIC
CORDIC是一种用移位和加法实现三角、双曲等函数的算法。CW32L012的CORDIC提供某些数学函数的硬件加速,特别是三角函数,通常用于电机控制、计量、信号处理和许多其他应用。与软件实现相比,它加快了这些功能的计算速度,允许较低的工作频率,或释放处理器周期以执行其他任务。
CW32L012的CORDIC支持余弦 cos、正弦 sin、相位角 atan2、模 hypot、反正切 atan、双曲余弦 cosh、双曲正弦 sinh、双曲反正切 atanh 函数运算。
CW32L012使用CORDIC运算100W次SIN30度与COS30度的代码实现如下:
int32_t angle;
void RCC_Configuration(void)
{
SYSCTRL_HSI_Enable(SYSCTRL_HSIOSC_DIV1);
SYSCTRL_HCLKPRS_Config(SYSCTRL_HCLK_DIV1);
SYSCTRL_PCLKPRS_Config(SYSCTRL_PCLK_DIV1);
SYSCTRL_SystemCoreClockUpdate(96000000);
}
void performance_test1(unsigned long iterations)
{
unsigned long i=0;
int32_t y1,y2;
float y11,y22;
for(i=1;i<=iterations;i++)
{
while (CORDIC_GetStatus().busy);
CW_CORDIC- >Z =angle; // 写入Z寄存器启动运算
// 等待运算完成
while (!CORDIC_GetStatus().eoc); //运算完成标志硬件置1,读取运算结果硬件清0
// 读取结果
//y1=CW_CORDIC->Y;//sin(PI/6); // 正弦结果在Y寄存器 Q1.31格式 根据需要使用
//y2=CW_CORDIC->X;//cos(PI/6); // 余弦结果在X寄存器 Q1.31格式 根据需要使用
//y11=q1_31_to_float(y1); //正弦结果转浮点数 根据需要使用
//y22=q1_31_to_float(y2); //余弦结果转浮点数 根据需要使用
}
}
void BTIM1_Configuration(void) //1ms进一次中断
{
BTIM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct = {0};
__SYSCTRL_BTIM123_CLK_ENABLE();
__disable_irq();
NVIC_EnableIRQ(BTIM1_IRQn);
__enable_irq();
BTIM_TimeBaseInitStruct.BTIM_Mode = BTIM_MODE_TIMER;
BTIM_TimeBaseInitStruct.BTIM_Period = 1000 - 1;
BTIM_TimeBaseInitStruct.BTIM_Prescaler = 96 - 1; // 8
BTIM_TimeBaseInit(CW_BTIM1, &BTIM_TimeBaseInitStruct);
BTIM_ITConfig(CW_BTIM1, BTIM_IT_UPDATE, ENABLE);
BTIM_Cmd(CW_BTIM1, ENABLE);
}
unsigned int timecount=0;
unsigned int lastcmputetime=0;
int main(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
char temp_buff1[4];
RCC_Configuration();//时钟配置
cordic_init_t init = {
.func = CORDIC_FUNC_COS, // 选择余弦函数
.scale = 0, // 不使用扩展范围
.format = CORDIC_FORMAT_Q1_31, // 使用q1.31格式
.iter = CORDIC_ITER_20, // 迭代次数
.comp = 1, // 硬件补偿伸缩因子
.ie = 0, // 禁用中断
.dmaeoc = 0, // 禁用DMA
.dmaidle = 0 // 禁用DMA空闲
};
CORDIC_Init(&init); //sin cos运算初始化
EAU_Init();// 初始化EAU
EAU_SetMode(EAU_MODE_UNSIGNED_DIV);// 设置为无符号除法模式
__SYSCTRL_GPIOC_CLK_ENABLE(); //GPIOC LED
GPIO_InitStruct.Pins = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init( CW_GPIOC, &GPIO_InitStruct);
GPIO_WritePin(CW_GPIOC,GPIO_PIN_13,GPIO_Pin_RESET);
BTIM1_Configuration(); //1MS
OLED_Init(); //清屏
OLED_Printf(0,0,OLED_6X8," SIN/COS COMPUTE Test ");
OLED_Printf(0,16,OLED_6X8," For 1000000 Times ");
OLED_Update();
angle = float_to_q1_31(0.167);//float_to_q1_15 // 0.25=1/4,即:运算45度=PI/4,换算为Q1.31格式, //0.167=1/6 PI/6=30度
while (1)
{
sprintf(temp_buff1, " CW32L012 start...... ");
OLED_Printf(0, 32, OLED_6X8, temp_buff1);
OLED_Printf(0, 48, OLED_8X16, " ");
OLED_Update();
timecount=0;
performance_test1(1000000);
lastcmputetime=timecount;
sprintf(temp_buff1, " CW32L012 used time: ");
OLED_Printf(0, 32, OLED_6X8, temp_buff1);
sprintf(temp_buff1, " %d mS ", lastcmputetime);
OLED_Printf(0, 48, OLED_8X16, temp_buff1);OLED_Update();
timecount=0;
while(timecount< 4000); //等待2S
}
}
void BTIM1_IRQHandler(void)
{
/* USER CODE BEGIN */
if (BTIM_GetITStatus(CW_BTIM1, BTIM_IT_UPDATE))
{
BTIM_ClearITPendingBit(CW_BTIM1, BTIM_IT_UPDATE);
timecount++;
}
/* USER CODE END */
}

运算结果:

计算100W次SIN30度 与COS30度。其中运算结果数据表示为:CORDIC运算结果为Q1.31格式表示;math.h:运算结果为浮点数表示。
时间对比参考如下:

审核编辑 黄宇
-
STM32F103
+关注
关注
34文章
499浏览量
68359 -
CW32
+关注
关注
1文章
326浏览量
1993
发布评论请先 登录
CW32L012的FOC电机驱动的运放电路设计解析
CW32L012电压电流表设计思路
基于STM32F103驱动DAC1220 20位/16位DAC数模转换模块输出可调±10V基准和三角波信号
基于STM32F103驱动AD9833模块 DDS信号发生器输出正弦波/三角波/方波可编程信号
FOC控制中如何利用芯片内部的运放设计电流采样电路?
CW32L012与STM32G431的CORDIC三角函数运算性能对比
CW32L012小型机器人控制评估板活动 四足机器人+智能小车 开箱评测
**CW32L012****开发评估板的第一个程序**
CW32L012小机器人的电机控制
使用芯源CW32的CW32L012开发评估板做了spi屏幕驱动
MH32F103A系列单片机的功能特性
在STM32F103c8上做DLQR最优控制算法的C编程资料
坚持继续布局32位MCU,进一步完善产品阵容,96Mhz主频CW32L012新品发布!
CW32L012与STM32F103的三角运算性能对比
评论