如何控制变量中的单个位?
How to control a single bit within a variable?
我正在 Microblaze 软件中开发 LCD 控制器 CPU 我已经嵌入到 FPGA 中。为了连接到顶层 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 数据总线可能是接下来的四位?
您可以在结构中创建位域:
typedef struct {
Uint32 LCD_RS : 1, /* 1 is the size in bit */
LCD_RW : 1,
LCD_E : 1,
bus : 4
: 15;
} data;
因为你想要一个非常精确定义的位控制方式,最安全的方式是使用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 端口寄存器映射添加 bit-set/bit 清除地址位置(这是 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' 信号。你知道它应该开始 low.The 整个过程变得更简单:
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!
对于读取,您不需要设置数据,但必须将读取线设置为高电平。但是LCD显示可以不用读取也可以操作
我正在 Microblaze 软件中开发 LCD 控制器 CPU 我已经嵌入到 FPGA 中。为了连接到顶层 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 数据总线可能是接下来的四位?
您可以在结构中创建位域:
typedef struct {
Uint32 LCD_RS : 1, /* 1 is the size in bit */
LCD_RW : 1,
LCD_E : 1,
bus : 4
: 15;
} data;
因为你想要一个非常精确定义的位控制方式,最安全的方式是使用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 端口寄存器映射添加 bit-set/bit 清除地址位置(这是 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' 信号。你知道它应该开始 low.The 整个过程变得更简单:
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!
对于读取,您不需要设置数据,但必须将读取线设置为高电平。但是LCD显示可以不用读取也可以操作