GPIO & AFIO
General-purpose I/Os & Alternate function I/Os
推挽输出与开漏输出
推挽输出 (push-pull,TTL/CMOS反相器)
- 输出驱动能力有限
- 无法直接 “线与”
开漏输出 (OC门,即集电极开路门)
- 必须有上拉电阻,否则只能输出低电平
- 驱动能力可由外接电源调节
- 可以直接 “线与”
寄存器声明与定义
- C语言在给结构体分配内存空间时,会给每个成员依次分配连续的地址空间,而GPIO的七个寄存器在内存映射中也被分配了连续的地址空间。所以只要在结构体内按照内存映射中分配的顺序声明成员,每个寄存器的地址就能够依次一一正确对应。
typedef struct
{
__IO uint32_t CRL;//volatile unsigned int CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
volatile的使用
- 由于IO口的寄存器值随时可能会变化,每次使用时应重新读取,故加上volatile防止编译器对其进行优化。
- 需要使用volatile的情况:
- 变量的值随时可能会变化
- 变量的值会受到其它共享此变量的寄存器的影响
时钟和复位 RCC
Reset & Clock Control
右移操作符
- Eg:
while( ! (RCC->CR>>17) );//判断RCC_CR第17位是否为 1
- RCC_CR是clock control register,第17位为外部高速时钟就绪标志位HSERDY,18-31位初始默认为0,更保险的写法为:
while( (RCC->CR >> 17) & 0x0001 == 0 );
- 运算操作符只在CPU的寄存器中进行,不影响内存的值。所以对RCC_CR移位并不会影响RCC_CR对应的映射内存中的值。
RCC->CR>>17;//不影响RCC_CR的值
RCC->CR = RCC->CR>>17;//会改变RCC_CR的值
- 第二条语句操作步骤为:
1.将内存中RCC_CR的值复制到CPU寄存器中;
2.在CPU寄存器中右移17位;
3.将CPU寄存器中的值复制回内存中
锁相环PLL
- u_d = u_i - u_o 的相位差,通过相位差来控制VCO频率的快慢,使输出的频率锁定在输入的频率上。假使在反馈线上增加一个N分频器,则 u_d = u_i - u_o/N,那么输出的频率则会锁定在N*输入的频率,即实现了N倍频。可用作时钟的倍频。