急急急
usart...对这一个确实得要好好看一下,连带着tim,(can?)之类的
旋转编码器测速:
- B相下降沿+A相低电平 -> 正转
- A相下降沿+B相低电平 -> 反转
不直接返回count主要是代码可移植性和封装的考虑 另外最好不要在主函数和中断函数里面操作同一个变量 有可能会出现未知bug
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) // GPIO_PinSource只能一个一个映射,不能按位或
- 杜邦线会对脉冲计数造成很大的影响,比如编码器之类的。
- 可以手动引出编码器的sw两个引脚(x)
为什么 GPIO 使用之前必须开时钟?
因为默认关闭不用的外设时钟可以降低功耗。
注意注意!这里PLL锁相环倍频可不止9倍,能设置到16倍频也就是128Mhz等于白嫖频率超频,可以提高oled的刷新率
- CSS (CSS Enabled) 检测晶振状态
- CNT -- ARR 常用上计数
- 影子寄存器改变ARR: 当CNT产生中断时会有 影子寄存器 -> 活动寄存器
初始化TIM: RCC -> ClockConfig(...)(时钟源等) -> 初始化TIM_TimeBaseInitTypeDef -> TIM_ITConfig(可以按位或) -> 对应NVIC -> 使能TIM
/* 定时器时基配置:决定 CNT 怎么计数 */ typedef struct { uint16_t TIM_Prescaler; // 预分频器 PSC // CNT时钟 = 定时器时钟 / (PSC + 1) // 0~65535 uint16_t TIM_CounterMode; // 计数模式:向上、向下或中央对齐计数 // TIM_CounterMode_Up ,TIM_CounterMode_Down // TIM_CounterMode_CenterAlignedx (x=1,2,3) uint16_t TIM_Period; // 自动重装值 ARR // 向上计数时:CNT从0数到ARR,然后重新从0开始 // 0~65535 uint16_t TIM_ClockDivision; // 定时器数字滤波器、死区等模块的时钟分频 -> 滤波器采样时间由当前tim和这个值决定 // 一般设为 TIM_CKD_DIV1;它不负责CNT的主要分频 // TIM_CKD_DIV1 ,TIM_CKD_DIV2 ,TIM_CKD_DIV4 uint8_t TIM_RepetitionCounter; // 重复计数器 RCR // 主要供高级定时器 TIM1/TIM8 使用,普通场景设为0 } TIM_TimeBaseInitTypeDef;/* 输出比较/PWM配置:决定一个通道怎样输出波形 */ typedef struct { uint16_t TIM_OCMode; // 输出比较模式,如 PWM1、PWM2、翻转模式等 uint16_t TIM_OutputState; // 是否使能普通输出通道 uint16_t TIM_OutputNState; // 是否使能互补输出 CHxN,仅 TIM1/TIM8 使用 uint16_t TIM_Pulse; // 比较值 CCRx // PWM模式下主要决定占空比:Duty ≈ CCR / (ARR + 1) uint16_t TIM_OCPolarity; // 普通通道输出极性:高有效或低有效 uint16_t TIM_OCNPolarity; // 互补通道输出极性,仅 TIM1/TIM8 使用 uint16_t TIM_OCIdleState; // 普通通道空闲时的电平,仅 TIM1/TIM8 使用 uint16_t TIM_OCNIdleState; // 互补通道空闲时的电平,仅 TIM1/TIM8 使用 } TIM_OCInitTypeDef;/* 输入捕获配置:决定在哪个输入边沿保存 CNT */ typedef struct { uint16_t TIM_Channel; // 选择捕获通道 CH1~CH4,捕获结果保存在对应CCRx uint16_t TIM_ICPolarity; // 捕获极性:上升沿或下降沿 uint16_t TIM_ICSelection; // 输入映射: // DirectTI = 通道直接连接对应输入 // IndirectTI = 通道交叉连接另一路输入 uint16_t TIM_ICPrescaler; // 捕获边沿分频:每1、2、4或8个有效边沿捕获一次 // 注意:它不改变CNT的计数速度 uint16_t TIM_ICFilter; // 输入数字滤波,0表示不滤波,0xF通常滤波最强 } TIM_ICInitTypeDef;
usart/uart:
typedef struct { uint32_t USART_BaudRate; uint16_t USART_WordLength; // USART_WordLength_8b // USART_WordLength_9b uint16_t USART_StopBits; // 停止位 // USART_StopBits_1, USART_StopBits_0_5, USART_StopBits_2, USART_StopBits_1_5 uint16_t USART_Parity; // 校验方式 // USART_Parity_No, USART_Parity_Even, USART_Parity_Odd // 还有更好用的CRC校验 uint16_t USART_Mode; // 收发 // USART_Mode_Rx, USART_Mode_Tx (|) uint16_t USART_HardwareFlowControl; // 增强数据传输(硬件流控),RTS CTS } USART_InitTypeDef;
USARTx_TX:GPIO_Mode_AF_PPUSARTx_RX:GPIO_Mode_IPU/GPIO_Mode_IN_FLOATINGvoid GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState); // 复用功能重映射usart初始化: RCC -> (PinRemap ->) GPIOInit(TX,RX) -> USARTInit -> (仅当要接收时: USART_ITConfig -> NVIC(USARTx) ) -> 使能
usart, IIC, SPI 都需要接GND; TTL, RS232, RS485电平标准
usart(with CLK) -- SPI
666 ctrl+alt+space 自动联想
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); uint16_t USART_ReceiveData(USART_TypeDef* USARTx); FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG); ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);USART_IT_TXE, USART_IT_RXNE(xxx)
发送时\r\n才表示换行
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // 接收 /* 读取 DR 会清除 RXNE,无需手动 ClearITPendingBit。 */ data = (uint8_t)USART_ReceiveData(USART1); while (1) { if (KeyScan() == 1) { // switch (KeyState) { // case ON: { // Serial_SendByte(USART2, 0x55); // break; // } // case OFF: { // Serial_SendByte(USART2, 0x56); // break; // } // } Serial_SendByte(USART2, 0x55); // 应该算是一种新的状态机的形式了吧 } }

浙公网安备 33010602011771号