我是第一次发帖,长期论坛搜索者...感谢您的关注。
我当前的嵌入式项目使用由 HD44780 标准控制器控制的 16x2 LCD。我的 PIC18 通过 Adafruit LCD 串行背包(原理图链接)与 LCD 对话。我选择了SPI接口。
HD44780 通过对 8 个数据引脚 (DB0-7)、一个读/写引脚 (R/W)、一个寄存器选择引脚 (RS) 和一个启用引脚 (E) 的各种指令写入来控制。 链接到指令集。
指令由指示某些设置的位组成……配置参数缺少更好的术语。
一切都按预期工作,但是,我的问题与最佳实践有关。为了最好地组织我的代码以提高可读性和灵活性,我尝试遵循以下方法:
- 通过头文件中的#define 指令分配每个 HD44780 配置参数
- 为每条指令构建一个 char 类型的数组,并使用适当的配置参数加载它
通过指针传递指令数组并使用移位操作以串行背包期望的顺序构造SPI输出来执行指令
这一切都很好,但是,我觉得将指令存储为数组并不是最好的方法。对于如何以清晰和高效的方式处理此问题的任何建议,我将不胜感激。
我的头文件和 .c 文件在下面,main.c 不包括在内,但通过指令别名调用 LCD_send。
头文件
/*
* File: LCD_SPI_16x2.h
* Author: rbs
* Comments:
* Revision history:
*/
/*Hardware configuration:
*
* Adafruit LCD serial backpack bit configuration:
* [DB4 | DB5 | DB6 | DB7 | E | RS | RW | LITE]
*
* HD44780 instruction set bit configuration (4-bit mode):
* [RS | RW | DB7 | DB6 | DB5 | DB4]
*
* HD44780 instruction set bit configuration (8-bit mode):
* [RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0]
*
* PIC18 MSSP1 SPI peripheral:
* LSB first, clock = FOSC/4, SCK idle = low, TX on SCK low -> high, SDI not used
*/
// This is a guard condition so that contents of this file are not included
// more than once.
#ifndef LCD_SPI_16X2_V2_H
#define LCD_SPI_16X2_V2_H
#include <xc.h> // include processor files - each processor file is guarded.
//function prototypes
//void LCD_init(void);
void LCD_send(char *cmd);
void LCD_spi_out(char data);
//void LCD_send_string(const char * str);
//void LCD_set_cursr(int row, int col);
#define _E 0x08 //alias for HD44780 ENABLE bit
//HD44780 LCD parameters
#define _BL 1 //1-> backlight on 0-> backlight off
#define _ID 1 // 1-> increment 0-> decrement
#define _S 0 // 1-> display shift 0-> no shift
#define _D 0 // 1-> display on 0-> display off
#define _C 0 // 1-> cursor on 0-> cursor off
#define _B 0 // 1-> cursor blinks 0-> cursor does not blink
#define _SC 0 // 1-> shift display 0-> shift cursor
#define _RL 0 // 1-> shift to the left 0-> shift to the right
#define _N 1 // 1-> 2 lines 0-> 1 line
#define _F 0 // 1-> 5x10 dot font 0-> 5x8 dot font
#define _DL8 1 // 8-bit mode
#define _DL4 0 // 4-bit mode
//HD44780 LCD instruction aliases
#define _Clear LCD_send(Clear_display)
#define _Home LCD_send(Home)
#define _Entry_mode LCD_send(Entry_mode)
#define _Display_onOff LCD_send(Display_onOff))
#define _Cursor_shift LCD_send(Cursor_shift)
#define _Function8 LCD_send(Function_set_8bit)
#define _Function4 LCD_send(Function_set_4bit)
//HD44780 LCD instruction set, see format note above
char Clear_display[10] = {0,0,0,0,0,0,0,0,0,1};
char Home[10] = {0,0,0,0,0,0,0,0,1,0};
char Entry_mode[10] = {0,0,0,0,0,0,0,1,_ID,_S};
char Display_onOff[10] = {0,0,0,0,0,0,1,_D,_C,_B};
char Cursor_shift[10] = {0,0,0,0,0,1,_SC,_RL,0,0};
char Function_set_8bit[10] = {0,0,0,0,1,_DL8,_N,_F,0,0};
char Function_set_4bit[10] = {0,0,0,0,1,_DL4,_N,_F,0,0};
char Cursor_pos[10] = {0,0,1,0,0,0,0,0,0,0};
#endif /* LCD_SPI_16X2_V2_H */
.C 文件
/*
* File: LCD_SPI_16x2.c
* Author: rbs
*
* Created on April 4, 2017, 10:00 PM
*/
#include <xc.h>
#include "system_initialize.h"
#include "LCD_SPI_16x2_v2.h"
void LCD_init(){
//not completed yet
}
void LCD_send(char *cmd){
/* Adafruit LCD serial backpack bit configuration:
* UPPER:
* [DB4 | DB5 | DB6 | DB7 | E | RS | RW | LITE]
* LOWER:
* [DB0 | DB1 | DB2 | DB3 | E | RS | RW | LITE]
* HD44780 incoming instruction configuration:
* [RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0]
*/
char Upper = 0x00;
char Lower = 0x00;
Upper |= (*(cmd))<<2; //set RS bit
Upper |= (*(cmd+1))<<1; //set RW bit
Upper |= (*(cmd+5))<<7; //set data bits for upper 4bits of command
Upper |= (*(cmd+4))<<6;
Upper |= (*(cmd+3))<<5;
Upper |= (*(cmd+2))<<4;
Upper |= _BL; //set back light bit
Lower |= (*(cmd))<<2; //set RS bit
Lower |= (*(cmd+1))<<1; //set RW bit
Lower |= (*(cmd+9))<<7; //set data bits for lower 4bits of command
Lower |= (*(cmd+8))<<6;
Lower |= (*(cmd+7))<<5;
Lower |= (*(cmd+6))<<4;
Lower |= _BL; //set back light bit
LCD_spi_out(Upper);
LCD_spi_out(Lower);
}
void LCD_spi_out(char data){
_CS = 0; //chip select = 0
SSP1BUF = (data|_E); //send out data with E pin high
__delay_ms(2);
_CS = 1; //clock data out of LCD backpack shift register
__delay_ms(2); //delay for HD44780 to process
_CS = 0; //chip select = 0
SSP1BUF = data; //send out data with E pin low to set HD44780
__delay_ms(2);
_CS = 1; //clock data out of LCD backpack shift register
__delay_ms(2);
}