0

我是第一次发帖,长期论坛搜索者...感谢您的关注。

我当前的嵌入式项目使用由 HD44780 标准控制器控制的 16x2 LCD。我的 PIC18 通过 Adafruit LCD 串行背包(原理图链接)与 LCD 对话。我选择了SPI接口。

HD44780 通过对 8 个数据引脚 (DB0-7)、一个读/写引脚 (R/W)、一个寄存器选择引脚 (RS) 和一个启用引脚 (E) 的各种指令写入来控制。 链接到指令集

指令由指示某些设置的位组成……配置参数缺少更好的术语。

一切都按预期工作,但是,我的问题与最佳实践有关。为了最好地组织我的代码以提高可读性和灵活性,我尝试遵循以下方法:

  1. 通过头文件中的#define 指令分配每个 HD44780 配置参数
  2. 为每条指令构建一个 char 类型的数组,并使用适当的配置参数加载它
  3. 通过指针传递指令数组并使用移位操作以串行背包期望的顺序构造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);
}
4

0 回答 0