最近在学STM32F4芯片,想用寄存器操作,在学到IO端口复用AF(Alternative Function)时,发现对于
GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)函数无法理解.而后拿纸算了算,恍然大悟,写下这篇笔记来记录和分享.
先贴上代码:
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)) ;
GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;
temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp;
GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2;
}
对于代码疑问有二:
1,为何写入PinSource和AF复用就可以对相应寄存器进行操作.
2,对于((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4))无法理解.
针对疑点查询IO复用映射表:
并代入 PA9 (0x09) 和GPIO_AF_USART1(0x07) 的数据发现GPIOA->AFR[1] |=0x0000 0070;
对应AFR高八位寄存器为0x0000 0070,其中PA9对应AFRH9[3:0]为7,即0111,为AF7
恰到好处的是GPIO_AF_USART1 为 0x07,所以恍然大悟:
((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4))
拆解为 先执行(uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07),即GPIO_PinSource与0x07相 "&" 后剔除高位byte,并获取GPIO_PinSource在寄存器中的位置,再 * 4,就是移动在 高位/低位寄存器 中的位置 乘以 一个半字(AFR中的一个位),如此便可以得到想写入寄存器中的 GPIO_AF_USART1 的数据. 即 0x0000 0070;
而GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4))是对 我们 想写入的 AFR寄存器 对应位的复位 (即是对应位置写入0000).
至此分析完成,可以得到我们想要进行寄存器操的 函数,即对对应位写入想要的AF.
对PA9写入GPIO_AF_USART1的代码示例如下:
GPIOA->AFR[1] &= ~(0xF<<4*1); //初始化复用端口
GPIOA->AFR[1] |= 0x7<<4*1; //PA9 复用为USATT1_TX
PA9是高八位,对应寄存器位AFR[1]中的AFRH9,我们想写入的AF是GPIO_AF_USART1,参考图一是AF7,即0x07,那么操作就是先初始化再写入0x7咯.
设计资源 培训 开发板 精华推荐
- EVAL_IPT015N10N5_TOLL:英飞凌针对大功率电机控制应用(如叉车或低速车)的逆变器级解决方案
- LTC2917 的典型应用 - 具有 27 个可选阈值和看门狗定时器的电压监控器
- 可变输出单节电池 80W 加热器元件功率级降压/升压参考设计
- AN56581, PowerPSoC - 为具有 DMX-512 接口的 MR-16 灯设计 LED 驱动器电路
- LTC1143L-ADJ 低压差双路 5V/2A、3.3V/1A 转换器的典型应用电路
- LT3089IDF 高效可调电源的典型应用电路
- 使用 ON Semiconductor 的 NCS37000 的参考设计
- 具有短路保护功能的 NCV78M15BDTRKG 15V 电流升压的典型应用
- 具有 5V 输出的 LT1076IR 正负转换器的典型应用
- 使用 NXP Semiconductors 的 TDA1522 的参考设计
- 仙工智能(SEER)2020 收官展会——东莞智博会,敬请期待
- 百万桩!国家电网建成全球最大充电桩服务网
- 仅128GB储存M1 MacBook Air现身教育机构页面
- 苹果重申对AR潜力看好并疑暗示未来相关设备
- 配备10Gb以太网接口的M1 Mac mini疑曝光
- MagSafe充电器想以15W全速充电 仅能用苹果20W适配器
- 三星新专利:用升降式摄像头的Galaxy Z Fold
- 苹果明年或推入门级AirPods和更小的AirPods Pro
- 中兴AXON 20 5G首发屏下摄像头:未来iPhone和Mate会跟进
- Redmi K30S至尊版不止配骁龙865:LPDDR5内存+UFS 3.1