stm32颜色搭配(STM32G474RE板卡试用体验)
stm32颜色搭配(STM32G474RE板卡试用体验)开发板分为上下两部分,上半部分为ST-LINK-V3仿真器,可以给开发板进行调试和程序下载。下半部分是G474的最小系统板:全IO引出,兼容流行的Arduino扩展口如下图所示。值得一提的是:上半部分的ST-LINK是可以通过断开跳帽之后可以单独作为调试器使用。STM32G474资源介绍:STM32G474开发板实物图:▲ 开发板实物图
开发环境:Keil uVision5(版本V5.28a),STM32CubeMX(版本V5.4)
运行平台:Window10企业版 64位系统
资源篇
外观还是一如既往的靓,简洁美观。板子搭载的是M4内核,速度快,高达170M主频,和数学运算加速器CORDIC大大提高运算能力, 输入电压范围1.71~3.6V,512Flash,128的SRAM,1个用户LED,一个用户按键,32.768khz的外部低速晶振,外接24M的高速晶振,Micro-AB连接器,Arduino™ Uno V3连接器可扩与Arduino™ Uno V3连接,板载STLINK_V3仿真调试器,调试器的主控是STM32F723,下载速度得到的很大的提高。
STM32G474资源介绍:
STM32G474开发板实物图:
▲ 开发板实物图
开发板分为上下两部分,上半部分为ST-LINK-V3仿真器,可以给开发板进行调试和程序下载。下半部分是G474的最小系统板:全IO引出,兼容流行的Arduino扩展口如下图所示。值得一提的是:上半部分的ST-LINK是可以通过断开跳帽之后可以单独作为调试器使用。
实战篇
测试内容:
- IO测试
- 虚拟串口VCP测试
- FPU测试
- DSP测试
1. LED和GPIO测试1
(1) 原理:短按一下按键,LED点亮,再短按一下按键LED熄灭。
(2) 步骤:使用CubeCubeMx生成工程。
▲ 引脚配置
时钟配置:外接24M晶振,高达170M主频
生成工程,固件包版本V1.1.0。
代码:
结果:短按一下按键,LED点亮,再短按一下按键LED熄灭。
结论:使用MX配置简单快速。
2. VCP虚拟串口测试1
(1) 原理:
MCU与stlik连接
虚拟串口连接MCU的LPUART1
(2) 配置工程:
相关代码:
(3)结果:如下所示,按一次按键就打印一个“OK”,LED一亮灭交替。
结论:这个功能在我们调试的时候十分方便,节省了很多的资源和时间。
3.FPU性能测试1
原理:
FPU浮点运算单元,如果CPU上没有FPU进行浮点运算的话必须按照IEEE标准进行运算十分的耗时,相较之下具有FPU的处理器在计算浮点运算是非常快的,G474Nucleo板载FPU运算加速器,运算性能非常出色,我们可以通过简单的测试来测一下板子的FPU的性能,可以通过计算使用FPU时单精度的乘除法使用的时间和没有使用FPU时消耗的时间进行比较来得出结论,其中时间的计数我们使用的是systick定时器。
步骤:
首先我们要学会打开硬件FPU,我们要设置 CPACR寄存器,其中在SystemInit函数中已经写好怎么配置,如下图:
我们只需要添加宏定义__FPU_PRESENT =1 ,_FPU_USED=1就可以了,而默认已经定义了__FPU_PRESENT =1,我们还需要添加_FPU_USED=1,在target 的Code Generation 选single Precision 就行了,如下图。
相关代码如下:
双精度和单精度计算函数
/**
* @name DoubleD
* @brief 双精度乘除法.
* @param angle:起始值,times:计算次数,
*mod:1除法0乘法
*/
void DoubleD(double angle uint32_t times uint8_t mode)
{
uint32_t i;
double result;
if(mode)//除法
{
for(i=0;i<times;i )
{
result = angle/PI;
angle = 0.00001f;
}
}
else//乘法
{
for(i=0;i<times;i )
{
result = angle*PI;
angle = 0.00001f;
}
}
}
/**
* @name FloatXFloat
* @brief 单精度乘除法.
* @param angle:起始值,times:计算次数,*mod:1除法0乘法
*/
void FloatXFloat(float angle uint32_t times uint8_t mode)
{
uint32_t i;
float result;
if(mode)//除法
{
for(i=0;i<times;i )
{
result = angle/PI;
angle = 0.00001f;
}
}
else//乘法
{
for(i=0;i<times;i )
{
result = angle*PI;
angle = 0.00001f;
}
}
}
主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*
/* Reset of all peripherals Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_LPUART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("---------------NOT USER FPU----------------------\n");
//-------------------测试单精度乘法----------------------------------------
start_tim = HAL_GetTick();
//乘法
FloatXFloat(PI/6 TIMES 0);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
printf("单精度乘法-- %d ms\r\n" tim_cnt); //显示运行时间
//-----------------测试单精度除法-------------------------------------------
start_tim = HAL_GetTick();
//除法
FloatXFloat(PI/6 TIMES 1);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
printf("单精度除法-- %d ms\r\n" tim_cnt); //显示运行时间
//-----------------测试双精度乘法-------------------------------------------
start_tim = HAL_GetTick();
//乘法
DoubleD(PI/6 TIMES 1);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
printf("双精度乘法-- %d ms\r\n" tim_cnt); //显示运行时间
//-----------------测试双精度除法-------------------------------------------
start_tim = HAL_GetTick();
//除法
DoubleD(PI/6 TIMES 1);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
printf("双精度除法-- %d ms\r\n" tim_cnt); //显示运行时间
HAL_GPIO_TogglePin(USER_LED_GPIO_Port USER_LED_Pin);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
测试结果:
条件:输入参数angle:起始值 = π/6,times:计算次数 = 20000(两万),mod:乘除法时。
(1)没有打开FPU
(2)打开FPU
数据比较
得出结论:
打开FPU和没有打开FPU在浮点计算性能上有明显的提高,测试中可以看出在单精度乘法上性能上比较明显,速度大概是没有打开FPU的9倍左右,单精度除法则提升没有那么高4.3倍左右,在双精度上的运算则没有起到作用,耗时基本相同,所以FPU在单精度上计算速度上比较快对于双精度计算则不起作用。
4. DSP测试1
原理:
M4内核除了集成硬件FPU外,还带有DSP指令,还有相应的加速单元增加了数据的处理能力和运算速度,ST还提供了DSP算法相关的库 ,大大的提高了我们开发速度和效率 ,为了展示DSP的性能,我使用ST提供的标准库数学运算的运算速度和使用DSP库的提供的数学函数的运算速度比较,参考原子的比较方式,现在我们用过sin(x)² cos(x)² = 1 这个运算,首先我们以x为变量,x从π/6开始,每次累加0.001,累加200000次,每次的结果的误差不能大于0.00005的运算时间进行比较,可以得到使用DSP和不使用DSP运算速度上的差别。
步骤:
在原来的工程上加入DSP库的头文件和源文件,并包含头文件路径,还要打开硬件FPU,添加宏定义 添加头文件和lib。
打开FPU,在target 的Code Generation 选singlePrecision。
减价宏定义ARM_MATH_CM4。
测试主要代码:
运算函数:
//sin cos测试
//angle:起始角度
//times:运算次数
//mode:0 不使用DSP库;1 使用DSP库
//返回值:0 成功;0XFF 出错
uint8_t sin_cos_test(float angle uint32_t times uint8_t mode)
{
float sinx cosx;
float result;
uint32_t i=0;
if(mode==0)
{
for(i=0;i<times;i )
{
cosx=cosf(angle); //不使用DSP优化的sin,cos函数
sinx=sinf(angle);
result=sinx*sinx cosx*cosx;//计算结果应该等于1
result=fabsf(result-1.0f);//对比与1的差值
if(result>DELTA)
{
return 0XFF; //判断失败
}
angle =0.001f; //角度自增
}
}
else
{
for(i=0;i<times;i )
{
cosx=arm_cos_f32(angle);//使用DSP优化的sin,cos函数
sinx=arm_sin_f32(angle);
result=sinx*sinx cosx*cosx; //计算结果应该等于1
result=fabsf(result-1.0f); //对比与1的差值
if(result>DELTA)
{
return 0XFF;//判断失败
}
angle =0.001f; //角度自增
}
}
return 0;//任务完成
}
函数中当输入参数mode为1时使用DSP库提供的arm_cos_f32和arm_sin_f32计算sin(x)² cos(x)² = 1,输入参数angle为其实角度,计算一次增加0.001 输入的参数timers是要计算的次数,计算的次数越多越消耗时间,对硬件的资源要求就越高,mode为1时则使用st标准库提供的sin,cos函数,所以通过两者的比较得出那种方式比较节省时间。
主函数
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_LPUART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//使用DSP优化
start_tim = HAL_GetTick();
status = sin_cos_test(PI/6 200000 1);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
if(status==0)
{
printf("USER DSP-- %d ms\r\n" tim_cnt); //显示运行时间
}
else
{
printf("USER DSP ERROR\n"); //显示当前运行情况
}
//不使用DSP优化
start_tim = HAL_GetTick();
status = sin_cos_test(PI/6 200000 0);
end_tim = HAL_GetTick();
if(end_tim > start_tim)
{
tim_cnt = end_tim - start_tim;
}
else
{
tim_cnt = 0xffffffff - start_tim end_tim;
}
if(status==0)
{
printf("NOT USER DSP-- %d-ms\r\n" tim_cnt); //显示运行时间
}
else
{
printf("NOT USER DSP ERROR\n"); //显示当前运行情况
}
HAL_GPIO_TogglePin(USER_LED_GPIO_Port USER_LED_Pin);
HAL_Delay(500);
参数:angle : 起始角度 = π/6 ; times : 运算次数 = 10 000(1万);
结果如下图:使用DSP是8ms,没有使用DSP是12ms;12/8= 1.5倍。
参数:angle : 起始角度 = π/6 ; times : 运算次数 = 100 000(10万);
结果如下图:使用DSP是86ms,没有使用DSP是129ms;129/86= 1.5倍。
参数:angle : 起始角度 = π/6 ; times : 运算次数 = 200000(20万);
结果如下图:使用DSP是172ms,没有使用DSP是258ms;258/172= 1.5倍。
总结:在单精度数学运算方面使用DSP加数的效果还是比较明显的,平均来说是没有说使用DSP的15倍。