[原创] [原创] 新驱动力MM32F031开发板评测3:发现和修正MM32F031库中的bug

我爱下载   2018-10-18 10:10 楼主
库函数bug更改——
GPIO_PinAFConfig()
在调试PWM输出函数过程中,发现一处MM32F031库函数的bug。样例代码库中TIM3_PWM_OUTPUT例程中使用的代码如下: //PWM输出初始化 //arr:自动重装值 //psc:时钟预分频数 void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //¿ªÆôGPIOBʱÖÓ //SYSCFG->CFGR|=0x1<<11; GPIOB->AFRL=0x10000; //大家注意这条为寄存器操作方式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //TIM3_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); 。。。 。。。 } 这里大家注意到 GPIOB->AFRL = 0x10000;这行代码采用了寄存器操作方式,而不是函数库操作方式,感觉非常不协调,于是我改成HAL_gpio库中提供的函数 void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF) 经过测试,使用GPIO_PinAFConfig()函数后,PWM的输出就消失了。如下为源库文件中函数代码: /** 注释省略 */ void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF) { uint32_t temp = 0x00; uint32_t temp_2 = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); assert_param(IS_GPIO_AF(GPIO_AF)); temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); if((GPIO_PinSource >> 0x03) ==0) { GPIOx->AFRL &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); temp_2 = GPIOx->AFRL | temp; GPIOx->AFRL = temp_2; } else { GPIOx->AFRH &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); temp_2 = GPIOx->AFRH | temp; GPIOx->AFRH = temp_2; } } 对照MM32F031的手册中的相关说明,AFRL和AFRH两个寄存器分别负责IO引脚序号为0-7和8-15的IO转换功能的配置,因此上述代码存在如下几处问题。
1、 ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4));该语句用于生成掩码时错误的。
2temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); 该语句用于生成统一的IO引脚号0-15的或码也是错误的。
鉴于上述问题,我修改的代码如下两种: 修改如下 void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF) { uint32_t temp = 0x00; uint32_t temp_2 = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); assert_param(IS_GPIO_AF(GPIO_AF)); // temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); if((GPIO_PinNum >> 0x03) ==0) { // GPIOx->AFRL &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); temp = ((uint32_t)(GPIO_AF) << ((uint32_t)GPIO_PinSource * 4)); GPIOx->AFRL &= ~((uint32_t)0xF<< ((uint32_t)GPIO_PinSource * 4)); temp_2 = GPIOx->AFRL | temp; GPIOx->AFRL = temp_2; } else { // GPIOx->AFRH &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)); temp = ((uint32_t)(GPIO_AF) << ((uint32_t)(GPIO_PinSource-8) * 4)); GPIOx->AFRH &= ~((uint32_t)0xF<< ((uint32_t)(GPIO_PinSource-8) * 4)); temp_2 = GPIOx->AFRH | temp; GPIOx->AFRH = temp_2; } } 经过测试,修改后代码是有效的。 此内容由EEWORLD论坛网友我爱下载原创,如需转载或用于商业用途需征得作者同意并注明出处 本帖最后由 我爱下载 于 2018-10-18 16:30 编辑

回复评论 (4)

之前由于没有充分理解库函数中GPIO_PinAFConfig的使用方法,因此将GPIO_PinSource的使用方法理解错误了,导致分析的一部分是有问题,已经将错误部分删除,但是剩下的部分我认为依然存在问题,因此保留了,希望大家批评指正。 本帖最后由 我爱下载 于 2018-10-18 16:28 编辑
点赞  2018-10-18 16:27
感谢支持
欢迎大家来到电机驱动控制技术天地,一起在EEworld交流、学习。
点赞  2018-10-18 23:38

楼主,其实你修改之后的代码和官方库函数中GPIO_PinAFConfig的代码就是·同一个意思啊

点赞  2019-10-18 14:06

我测试过了,操作官方的库函数中GPIO_PinAFConfig和直接操作寄存器都可以实现PWM输出哦

 

点赞  2019-10-18 14:07
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复