0

我正在开发嵌入 FPGA 的 Microblaze 软 CPU 中的 LCD 控制器。为了连接到顶级 Verilog 文件的输出,我使用了一个 8 位 GPO。

在我的 C 语言中,我为我控制的每个位使用了占位符变量,例如:

LcdDataBus = (cmd & 0xF0);  //Send higher nibble
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 1;

如果我正在编程 PIC,我可以简单地将每个定义为 uC 上的一个引脚,即#define LCD_RS PORTA,0.

但是,我相信我只能通过函数访问端口

data = XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);
data = XIOModule_Start(&gpo);

data变量在哪里。

有没有办法我可以输入#define一位data,所以 LCD_RS = bit0,LCD_RW = bit1,LCD_E = bit3,我的 LCD 数据总线可能是接下来的四位?

4

2 回答 2

0

您可以在结构中创建位域:

typedef struct {
  Uint32 LCD_RS : 1, /* 1 is the size in bit */
         LCD_RW : 1,
         LCD_E  : 1,
         bus    : 4
                : 15;
} data;
于 2018-06-20T12:46:04.413 回答
0

由于您想要一种非常精确定义的位控制方式,因此最安全的方法是使用 read-modify-write。

volatile uint32_t *reg_address;
uint32_t data;
   data  = *reg_address;
   data |= (1<<LCD_RS_BIT_POS); // Set bit 
   // data &= ~(1<<LCD_RS_BIT_POS); // Clear bit 
   *reg_address = data;

另一种方法是将位设置/位清除地址位置添加到 LCD 端口寄存器映射(这是 Verilog 代码):

if (cpu_select && cpu_write)
  case (cpu_address[4:2])
  3'h0 : lcd_reg <= cpu_wdata[7:0]; // Direct write
  3'h1 : lcd_reg <= lcd_reg  |  cpu_wdata[7:0]; // set bit(s) write
  3'h2 : lcd_reg <= lcd_reg  & ~cpu_wdata[7:0]; // Clear bit(s) write
  ....
  endcase

您要求设置更多位。
一种基本方法是清除所有要更改的位,然后使用所需值再次设置它们。

例如:您有一个 4 位值(位 4、5、6、7)一个 R/W 位 (2) 加上一个地址位 (0)。你把它们变成一个面具:0b11110101。

   // Write to LCD
   data  = *reg_address;
   data &= ~0xF5; // Clear all the bits
   if (address==1)
     data |= (data_nibble<<4) | (1<<LCD_WRT_BIT_POS)  |(1<<LCD_ADR_BIT_POS) ; 
   else // Address 0 
     data |= (data_nibble<<4) | (1<<LCD_WRT_BIT_POS); 
   *reg_address = data;

但是....
在您的情况下,您可能只需要单独控制“E”信号。而且你知道它应该从低开始。整个过程变得更简单:

   uint32_t data;

   // Set the data, R/Wnot and RS all at the same time 
   if (write_data)
      data = nibble_data<<4; // R/Wn=0, RS=0. E=0
   else // Write command 
      data = nibble_data<<4 | (1<<RS_BIT_POS); // R/Wn=0, RS=1, E=0
   *reg_address = data;

   // Pulse E high and low:
   *reg_address = data | (1<<E_BIT_POS); // E high
   some_kind_of_wait_routine(); // Wait a while

   *reg_address = data; // E low 
   some_kind_of_wait_routine();  // Wait a while to guarantee minimum low time!

对于读取,您不需要设置数据,但您必须将读取线设置为高电平。然而,液晶显示器可以在不读取的情况下进行操作。

于 2018-06-20T12:58:17.190 回答