首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在STM32 L476RG上读取PS/2键盘扫描代码

在STM32 L476RG上读取PS/2键盘扫描代码
EN

Stack Overflow用户
提问于 2022-11-29 06:00:20
回答 1查看 44关注 0票数 1

我正在尝试从STM32 L476RG (核心L476RG开发板)上的PS/2键盘读取扫描代码。

PS/2和USART:

我相信我可以使用STM32上的USART硬件来读取PS/2数据,如果有什么原因的话请帮我理解。从我的阅读和带有作用域的观察来看,PS/2协议在数据线上发送以下数据包格式:

  1. 1开始位。这个总是0。
  2. 8位数据位,最不重要位优先。
  3. 1奇偶校验位。
  4. 1停位。这永远是1。

每一位被捕获在一个单独的时钟信号的下降边缘,这个时钟信号高度空闲。我的键盘上的时钟位于13.1 kHz左右。

如果给3.3V的电源,这两个系统都将从键盘输出3.3V,这是一个范围跟踪鞋,当连接到STM32时,这些波形很好。

出了什么问题

基本上,当按下键时,系统不会产生中断。RXNE (接收缓冲区,而不是空标志)保持低水平,不产生中断。

下面我将详细介绍,但是如果我在"0x55“模式下使用自动波特率,则会触发中断,但这只是因为设置了自动波特率错误标志。所有其他模式都什么也不做(没有中断)。

我试过什么

我使用以下代码在USART1上初始化要从键盘读取的STM32:

代码语言:javascript
运行
复制
void init_keyboard(uint32_t baud)
{
// Enable clock to GPIOA
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

// Enable clock to USART1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

// Configure UART
USART1->CR1 |= USART_CR1_RE  |   // Receiver enabled
               USART_CR1_PCE |   // Parity control enabled
               USART_CR1_PS  |   // Odd parity
               USART_CR1_M0  |   // 8 data bits
               USART_CR1_RXNEIE; // Enable RX interrupt

USART1->CR1 &= ~(USART_CR1_TE);

USART1->CR2 |= USART_CR2_CLKEN     | // Enable USART clock (sync mode)
               USART_CR2_ABREN     | // Enable auto Baud Rate
               USART_CR2_CPOL;       // Clock polarit 1 (idle high)


// The following need to be cleared for sync mode
USART1->CR2 &= ~(USART_CR2_LINEN);
USART1->CR3 &= ~(USART_CR3_SCEN  |
                 USART_CR3_HDSEL |
                 USART_CR3_IREN);

USART1->BRR |= (SystemCoreClock / baud); // set baud rate

USART1->CR1 |= USART_CR1_UE;

NVIC->ISER[1] |= (1 << (USART1_IRQn & 0x1F));

// Configure AF pins 8 and 10 to AF7 (USART)
GPIOA->AFR[1]  |= (GPIO_AF7_USART1 << 0);
GPIOA->AFR[1]  |= (GPIO_AF7_USART1 << 8);

// Configure PA8 (CK) and PA10 (RX) in alt. func. mode
GPIOA->MODER &= ~(GPIO_MODER_MODE8   | GPIO_MODER_MODE10);
GPIOA->MODER |=  (GPIO_MODER_MODE8_1 | GPIO_MODER_MODE10_1);

// Enable Global Interrupts
__enable_irq();
}

默认情况下,数据位是LSB,默认情况下捕获位于第一边缘(下降边缘),我确认此波特率/备用函数代码在9600波特的标准UART连接上工作。

我也尝试使用自动波特率检测,因为键盘的波特率似乎在一整天都在漂移(12.9-13.2 kHz),我不相信波特率是稳定的。我尝试了自动波特率和没有自动波特率,我尝试了自动波特率在所有4种模式:(开始位测量,跌落测量,0x55帧检测,0x7F帧检测)。--唯一给我任何东西的是0x7F,每当我读取0x55以外的代码时,它就抛出一个自动波特率错误(除了'+‘按下一个键),但是当我用0x55 (按’+‘键)发送一个帧时,它什么也不做。

为了防止你想知道,我在main调用了这个函数。:)

代码语言:javascript
运行
复制
/* ISR for handling keypresses */
void USART1_IRQHandler(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  init_keyboard(13120);

  while (1) {/* wait for interrupts */ }
}


void USART1_IRQHandler(void)
{
    if (USART1->ISR & USART_ISR_RXNE)
    {
        char read_byte = USART1->RDR;
        while (1) {/* catch here for debugging */ }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-30 06:29:06

感谢Flexz发现了以下内容:

STM32L476缺少CR2寄存器中的同步从描述部分和SLVEN位,这两个部分都存在于STM32L4+系列中,即L476只能是USART模式下的主程序。

这意味着我不能从PS/2设备中读取数据,至少不用时钟。我可以,但是仍然异步地从RX端口读取。这意味着我不想在USARTx->CR2中启用CLKEN。

如果异步处理行,则可以使用模式00中的自动波特率来捕获数据,即使波特率漂移,就像它在此键盘上所做的那样。

最终代码:

代码语言:javascript
运行
复制
void init_keyboard(uint32_t baud)
{
    //clear_buffer();

    // Enable clock to GPIOA
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

    // Enable clock to USART1
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

    // Configure UART
    USART1->CR1 |= USART_CR1_RE  |   // Receiver enabled
                   USART_CR1_PCE |   // Parity control enabled
                   USART_CR1_PS  |   // Odd parity
                   USART_CR1_M0  |   // 8 data bits
                   USART_CR1_RXNEIE; // Enable RX interrupt

    USART1->CR1 &= ~(USART_CR1_TE);

    USART1->CR2 |= USART_CR2_ABREN;  // Enable auto Baud Rate

    USART1->CR3 |= USART_CR3_OVRDIS; // Disable overrun detection

    USART1->BRR |= (SystemCoreClock / baud);

    USART1->CR1 |= USART_CR1_UE;

    NVIC->ISER[1] |= (1 << (USART1_IRQn & 0x1F));

    // Configure AF pin10 to AF7 (USART)
    GPIOA->AFR[1]  |= (GPIO_AF7_USART1 << 8);

    // Configure PA10 (RX) in alt. func. mode
    GPIOA->MODER &= ~(GPIO_MODER_MODE10);
    GPIOA->MODER |=  (GPIO_MODER_MODE10_1);

    // Enable Global Interrupts
    __enable_irq();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74609713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档