stm32f4将16位写入/读入两个8位gpio端口

时间:2018-01-21 08:52:40

标签: stm32 gpio

我尝试将16位数据写入两个选定的8位gpio端口。我必须拆分数据 LSB和MSB:

void LCD_write_command(uint16_t cmd) {
    GPIOD->ODR = cmd & 0x00ff; //lsb
    GPIOA->ODR = (GPIOA->ODR & 0x00ff) | (cmd >> 8); //msb
}

并读取数据:

uint16_t LCD_read_data(void) {
    (here is instruct gpio as input)
    volatile uint16_t data = 0;
    data  = (uint16_t)GPIOD->IDR & 0x00ff; //lsb
    data |= (uint16_t)GPIOA->IDR << 8 ; // msb
    (here is instruct gpio as output)
    return data;
}

当我使用一个16位gpio来编写和阅读时,一切都很好:

 void LCD_write_command(uint16_t cmd) {
    GPIOD->ODR = cmd & 0xffff; 
}
uint16_t LCD_read_data(void) {
    volatile uint16_t data = 0;
    data  = (uint16_t)GPIOD->IDR & 0xffff; 
    return data;
}

我接力不知道我失踪了什么。

3 个答案:

答案 0 :(得分:1)

您需要了解有关按位操作的更多信息。

  1. 书写

    void LCD_write_command(uint16_t cmd) {
       uint32_t tmp = GPIOD->ODR;
    
       tmp &= ~(0xff);
       tmp |= (cmd & 0x00ff);  
       GPIOD->ODR = tmp; //lsb
       tmp = GPIOA->ODR;
       tmp &= ~(0xff);
       tmp |= (cmd >> 8);
       GPIOA->ODR = tmp; //msb
    }
    
  2. void LCD_write_command(uint16_t cmd) {
       *(volatile uint8_t *)&GPIOD->ODR = cmd & 0xff;
       *(volatile uint8_t *)&GPIOA->ODR = cmd >> 8; //msb
    }
    

    强制编译器使用8位存储指令。

    在使用非字访问寄存器之前,如果您的micro允许,请检查RM: enter image description here

答案 1 :(得分:0)

你的非吸烟代码对我有用,下面是用LCD处理的原始源代码:

void LCD_write_command(uint16_t cmd) {
    GPIOB->BRR = LCD_CS;       // LCD_CS low (chip select pull)
    GPIOB->BRR = LCD_RS;       // LCD_RS low (register select = instruction)
    //GPIOA->ODR = cmd;         // put cmd to PortA (full length)
    // put cmd [0..12] bits to PortA (actual LCD_DB00..LCD_DB12)
    // put cmd [13..15] bits to PortB (actual LCD_DB13..LCD_DB15)
    GPIOA->ODR = cmd & 0x1fff;
    GPIOB->ODR = (GPIOB->ODR & 0xfff8) | (cmd >> 13);
    GPIOB->BRR = LCD_WR;       // pull LCD_WR to low (write strobe start)
    // Write strobe 66ns long by datasheet. GPIO speed on STM32F103 at 72MHz slower -> delay is unnecessary
    // asm volatile ("nop");
    GPIOB->BSRR = LCD_WR;      // pull LCD_WR to high (write strobe end)
    GPIOB->BSRR = LCD_CS;      // LCD_CS high (chip select release)
}

我检查了RM,我可以操作8位,半字和字。

答案 2 :(得分:0)

wtite_bits(uint16_t cmd)
{
    uint32_t data = GPIOA -> ODR;

    data &= ~(0x1fff);
    data |= cmd & 0x1fff;
    GPIOA -> ODR = data;

    data = GPIOB -> ODR;
    data &= ~(0x0007);
    data |= (cmd & 0x8fff) >> 13;
    GPIOB -> ODR = data;
}

保留寄存器中的其他位