bit-manipulation - 通过位操作生成正交信号

标签 bit-manipulation bitwise-operators bit stm32

我尝试生成正交信号,但使用尽可能最低的操作。我使用 STM32 和 GPIO 引脚 B8 和 B9 来发送信号。 引脚 8 和 9 有四种可能的选项,按顺时针方向排列: 0/0 1/0 1/1 和 0/1 和逆时针 0/0 0/1 1/1 1/0 我找不到按位快速设置或重置所选引脚的位的方法。 此外,我必须能够顺时针或逆时针转动,并在我想要的时候改变方向,就像它是旋转或线性编码器一样。

感谢您的帮助

最佳答案

位敲击

按位思维,B9得到B8之前的值,B8得到B9的倒数,倒数时反之亦然。您交换这两个位,并根据方向与 0x1000x200 进行异或。

inline void incB89(int down) {
    uint32_t temp;

    /* read the current output state */
    temp = GPIOB->ODR;

    /* modifying the significant bit-pair
       don't care about overflow */
    temp = (((temp & 0x100) << 1) | ((temp & 0x200) >> 1)) ^ (0x100 << down);

    /* Setting the reset bits BR8 and BR9. This has the effect that
       bits 8 and 9 will be copied into the ODR, and the rest will
       be left alone */
    temp |= ((1 << 24) | (1 << 25));

    GPIOB->BSRR = temp;
}

使用计时器(或两个)

在大多数 STM32 系列 Controller 上,TIM4 channel 3 和 4 输出可以映射到 PB8 和 PB9。如果您有其中之一,则该定时器可以自主控制输出,而不受代码、内存或中断延迟的影响。

  • 根据 Controller 的引用手册设置 GPIO 模式和复用功能寄存器。
  • 将 channel 3 和 4 均配置为切换模式,将 TIM4->CCMR1 中的 OC1MOC2M 位设置为 0b011
  • 设置输入时钟、预分频器 PSC 并重新加载 ARR 以达到所需频率的两倍,因为每个输出都会在每个定时器周期内切换一次。
  • 设置 TIM4->CCR3=0TIM4->CCR4=(TIM4->ARR+1)/2 以进行单向计数。交换它们(当计数器停止时)以反转方向。
  • 启用 TIM4->CCER 中的输出。
  • 您可以通过设置或重置 TIM4->CR1CEN 位来开始和停止计数。
  • 要对周期进行计数,您可以在 TIM4->DIER 中配置切换或更新事件的中断,或使用另一个计时器作为 TIM4 的从属计时器。

使用例如TIM3 进行计数:

  • TIM4->CR2 中的 MMS 位设置为 0b010,以便在每次溢出时输出触发脉冲。
  • TIM3->SMCR配置为外部时钟模式1,并选择TIM4的内部触发。
  • TIM3->ARR 设置为所需的半周期数 - 1。
  • 配置更新中断。
  • 启动计数器。

定时器还有更多技巧,例如使用从机触发的 DMA 突发来更新主定时器的 ARR 和 CCR 寄存器,其中“波长长度”值。

关于bit-manipulation - 通过位操作生成正交信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45964607/

相关文章:

c - 32 位和 64 位机器中的位操作

bitmap - 按位运算符的优先顺序

java - ~和++在java中的优先级

f# - 在 F# 中反转位

检查 C 中的位 - 错误答案?

file.txt的Java位处理

c - 在 9 位架构中搜索 8 位对齐的字符串

java - Java 中从部分 32 位值计算部分十进制值的最佳方法是什么

C 转换 double ->long -> Short (使用右移 ">>")

c - 用条件循环每个数字的最快方法