(十六)树莓派3B+ wiringPi库的使用--硬件SPI驱动NOKIA5110液晶

在这篇文章《stm8 软件模拟IIC驱动PCF8563T,NOKIA5110液晶显示》中使用的是STM8的硬件SPI驱动的NOKIA5110液晶。现在手里有树莓派,刚好wiringPi库也有SPI接口,这次就使用硬件SPI驱动NOKIA5110液晶。

NOKIA5110液晶介绍

在这里插入图片描述
NOKIA5110液晶是拆机屏幕,84*48的分辨率,接口为串行SPI(SPI-百度百科)接口。
关于这个的详细介绍可以看看《Nokia5110液晶屏新手学习笔记,一看就懂,特别简单哦,如果需要资料,可以来问班长我要啊》,这里介绍的还是比较详细的。资料下载地址:http://pan.baidu.com/s/1pJI8hp5

NOKIA5110液晶引脚说明

  1. RST ——复位
  2. CE —— 片选
  3. DC —— 数据/指令选择
  4. DIN —— 串行数据线
  5. CLK —— 串行时钟线
  6. VCC —— 电源输入(3.3v和5v均可,经过实验验证,没有问题)
  7. BL —— 背光控制端(接电源正极或者用GPIO端口控制都可以)
  8. GND —— 地线

树莓派和NOKIA5110液晶的连接

这次使用的硬件SPI,所以在使用树莓派的GPIO连接时需要接到对应的SPI端口,树莓派3B+有两组SPI,这里我使用的是SPI0
先看看树莓派的引脚图:
在这里插入图片描述
我们需要关注的是wPi这一栏。

NOKIA5110树莓派3B+ (wPi)
RSTGPIO.29(29)
CECE0(10)
DCGPIO.28(28)
DinMOSI(12)
ClkSCLK(14)
Vcc3.3v)
BL3.3 v
Gnd0v

开启树莓派的SPI接口

方式一:
使用raspi-config命令打开这个页面:
在这里插入图片描述
进入第5项,然后你就会看见SPI选项的,然后开启就是。最后记得重启reboot一下树莓派。
方式二:VNC登录树莓派桌面
在这里插入图片描述
在这里插入图片描述
保险起见还是,最后记得重启reboot一下树莓派。

wiringPi的SPI介绍

在代码实现之前先看看wiringPi–SPI部分。

  1. 引入头文件:#include <wiringPiSPI.h>
  2. 初始化SPI:int wiringPiSPISetup (int channel, int speed) ;
    这个事选择SPI通道,和速率。
    channel只有0和1这两个值,表示初始化哪个SPI通道;
    speed的范围是500000 到32000000,这个是SPI通讯的速度范围,单位是Hz。
    当这个函数返回值是负数的时候,表示SPI初始化失败。这是需要检查一下电路连接和是否开启了树莓派的SPI
  3. 开始数据传输:int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ;
    channel只有0和1这两个值,表示初始化哪个SPI通道;
    data要传输的字节,十六进制;
    len传输的字节长度。

代码实现

#include <wiringPi.h>
#include <stdio.h>  
#include <wiringPiSPI.h>

#define LCD_DC  28     // 模式选择 1:写数据 0:写命令
#define LCD_DIN 12     // 串行数据线
#define LCD_CLK 14     // 串行时钟线
#define LCD_RST 29     // 复位信号  低电平有效
#define LCD_CE  10     // 芯片使能  低电平有效


#define u16 unsigned int 
#define u8  unsigned char

#define X_Col_addr  0x80  // 定位列 地址 0-83
#define Y_Row_addr  0x40  // 定位行 地址 0-5
				
u8  Font_[][6] = {
{0x00,0x00,0x00,0x00,0x00,0x00},// (0)
{0x00,0x00,0x00,0x4F,0x00,0x00},//!(1)
{0x00,0x00,0x07,0x00,0x07,0x00},//"(2)
{0x00,0x14,0x7F,0x14,0x7F,0x14},//#(3)
{0x00,0x24,0x2A,0x7F,0x2A,0x12},//$(4)
{0x00,0x23,0x13,0x08,0x64,0x62},//%(5)
{0x00,0x36,0x49,0x55,0x22,0x50},//&(6)
{0x00,0x00,0x05,0x03,0x00,0x00},//'(7)
{0x00,0x00,0x1C,0x22,0x41,0x00},//((8)
{0x00,0x00,0x41,0x22,0x1C,0x00},//)(9)
{0x00,0x14,0x08,0x3E,0x08,0x14},//*(10)
{0x00,0x08,0x08,0x3E,0x08,0x08},//+(11)
{0x00,0x00,0x50,0x30,0x00,0x00},//,(12)
{0x00,0x08,0x08,0x08,0x08,0x08},//-(13)
{0x00,0x00,0x60,0x60,0x00,0x00},//.(14)
{0x00,0x20,0x10,0x08,0x04,0x02},///(15)
{0x00,0x3E,0x51,0x49,0x45,0x3E},//0(16)
{0x00,0x00,0x42,0x7F,0x40,0x00},//1(17)
{0x00,0x42,0x61,0x51,0x49,0x46},//2(18)
{0x00,0x21,0x41,0x45,0x4B,0x31},//3(19)
{0x00,0x18,0x14,0x12,0x7F,0x10},//4(20)
{0x00,0x27,0x45,0x45,0x45,0x39},//5(21)
{0x00,0x3C,0x4A,0x49,0x49,0x30},//6(22)
{0x00,0x01,0x71,0x09,0x05,0x03},//7(23)
{0x00,0x36,0x49,0x49,0x49,0x36},//8(24)
{0x00,0x06,0x49,0x49,0x29,0x1E},//9(25)
{0x00,0x00,0x36,0x36,0x00,0x00},//:(26)
{0x00,0x00,0x56,0x36,0x00,0x00},//;(27)
{0x00,0x08,0x14,0x22,0x41,0x00},//<(28)
{0x00,0x14,0x14,0x14,0x14,0x14},//=(29)
{0x00,0x00,0x41,0x22,0x14,0x08},//>(30)
{0x00,0x02,0x01,0x51,0x09,0x06},//?(31)
{0x00,0x32,0x49,0x79,0x41,0x3E},//@(32)
{0x00,0x7E,0x11,0x11,0x11,0x7E},//A(33)
{0x00,0x7F,0x49,0x49,0x49,0x3E},//B(34)
{0x00,0x3E,0x41,0x41,0x41,0x22},//C(35)
{0x00,0x7F,0x41,0x41,0x22,0x1C},//D(36)
{0x00,0x7F,0x49,0x49,0x49,0x41},//E(37)
{0x00,0x7F,0x09,0x09,0x09,0x01},//F(38)
{0x00,0x3E,0x41,0x49,0x49,0x7A},//G(39)
{0x00,0x7F,0x08,0x08,0x08,0x7F},//H(40)
{0x00,0x00,0x41,0x7F,0x41,0x00},//I(41)
{0x00,0x20,0x40,0x41,0x3F,0x01},//J(42)
{0x00,0x7F,0x08,0x14,0x22,0x41},//K(43)
{0x00,0x7F,0x40,0x40,0x40,0x40},//L(44)
{0x00,0x7F,0x02,0x04,0x02,0x7F},//M(45)
{0x00,0x7F,0x04,0x08,0x10,0x7F},//N(46)
{0x00,0x3E,0x41,0x41,0x41,0x3E},//O(47)
{0x00,0x7F,0x09,0x09,0x09,0x06},//P(48)
{0x00,0x3E,0x41,0x51,0x21,0x5E},//Q(49)
{0x00,0x7F,0x09,0x19,0x29,0x46},//R(50)
{0x00,0x46,0x49,0x49,0x49,0x31},//S(51)
{0x00,0x01,0x01,0x7F,0x01,0x01},//T(52)
{0x00,0x3F,0x40,0x40,0x40,0x3F},//U(53)
{0x00,0x1F,0x20,0x40,0x20,0x1F},//V(54)
{0x00,0x3F,0x40,0x38,0x40,0x3F},//W(55)
{0x00,0x63,0x14,0x08,0x14,0x63},//X(56)
{0x00,0x03,0x04,0x78,0x04,0x03},//Y(57)
{0x00,0x61,0x51,0x49,0x45,0x43},//Z(58)
{0x00,0x00,0x7F,0x41,0x41,0x00},//[(59)
{0x00,0x15,0x16,0x7C,0x16,0x15},//\(60)
{0x00,0x00,0x41,0x41,0x7F,0x00},//](61)
{0x00,0x04,0x02,0x01,0x02,0x04},//^(62)
{0x00,0x40,0x40,0x40,0x40,0x40},//_(63)
{0x00,0x00,0x01,0x02,0x04,0x00},//`(64)
{0x00,0x20,0x54,0x54,0x54,0x78},//a(65)
{0x00,0x7F,0x48,0x44,0x44,0x38},//b(66)
{0x00,0x38,0x44,0x44,0x44,0x20},//c(67)
{0x00,0x38,0x44,0x44,0x48,0x7F},//d(68)
{0x00,0x38,0x54,0x54,0x54,0x18},//e(69)
{0x00,0x08,0x7E,0x09,0x01,0x02},//f(70)
{0x00,0x0C,0x52,0x52,0x52,0x3E},//g(71)
{0x00,0x7F,0x08,0x04,0x04,0x78},//h(72)
{0x00,0x00,0x44,0x7D,0x40,0x00},//i(73)
{0x00,0x20,0x40,0x44,0x3D,0x00},//j(74)
{0x00,0x7F,0x10,0x28,0x44,0x00},//k(75)
{0x00,0x00,0x41,0x7F,0x40,0x00},//l(76)
{0x00,0x7E,0x02,0x0C,0x02,0x7C},//m(77)
{0x00,0x7E,0x04,0x02,0x02,0x7C},//n(78)
{0x00,0x38,0x44,0x44,0x44,0x38},//o(79)
{0x00,0x7C,0x14,0x14,0x14,0x08},//p(80)
{0x00,0x08,0x14,0x14,0x18,0x7C},//q(81)
{0x00,0x7C,0x08,0x04,0x04,0x08},//r(82)
{0x00,0x48,0x54,0x54,0x54,0x20},//s(83)
{0x00,0x04,0x3F,0x44,0x40,0x20},//t(84)
{0x00,0x3C,0x40,0x40,0x20,0x7C},//u(85)
{0x00,0x1C,0x20,0x40,0x20,0x1C},//v(86)
{0x00,0x3C,0x40,0x30,0x40,0x3C},//w(87)
{0x00,0x44,0x28,0x10,0x28,0x44},//x(88)
{0x00,0x0C,0x50,0x50,0x50,0x3C},//y(89)
{0x00,0x44,0x64,0x54,0x4C,0x44},//z(90)
{0x00,0x00,0x08,0x36,0x41,0x00},//{(91)
{0x00,0x00,0x00,0x7F,0x00,0x00},//|(92)
{0x00,0x00,0x41,0x36,0x08,0x00},//}(93)
{0x00,0x08,0x04,0x08,0x10,0x08},//~(94)
{0x00,0x08,0x08,0x2A,0x1C,0x08},//→(127)
{0x00,0x08,0x1C,0x2A,0x08,0x08},//←(128)
{0x00,0x04,0x02,0x7F,0x02,0x04},//↑(129)
{0x00,0x10,0x20,0x7F,0x20,0x10},//↓(130)
{0x00,0x1C,0x2A,0x32,0x2A,0x1C},//笑面(131)
{0x00,0x1C,0x22,0x44,0x22,0x1C}};//爱心(132)
 
/*--------------------------------------------------------------*/

// 初始化GPIO 端口
void gpioInit(){
    pinMode(LCD_DC,OUTPUT);
    pinMode(LCD_RST,OUTPUT);
    pinMode(LCD_CE,OUTPUT);
}

// 往LCD写入数据
// wbyte: 需要写入的数据
// dat_cmd: 1-数据 0-命令 
void lcd_writeByte(u8 wbyte, u8 dat_cmd){
    digitalWrite(LCD_CE,LOW);
    if (dat_cmd == 1) { // 写数据
        digitalWrite(LCD_DC,HIGH);
    }
    else { // 写命令
        digitalWrite(LCD_DC,LOW);
    }
    u8 *tempData = &wbyte;
    wiringPiSPIDataRW(0, tempData, 1);
    digitalWrite (LCD_CE, HIGH);
}
// 液晶清屏
void lcd_clear(){
    u16 i;
    lcd_writeByte(X_Col_addr,0);
    lcd_writeByte(Y_Row_addr,0);
    // 84*48的LCD点阵液晶  那么84x48=504
    for(i = 0; i < 504; i ++){
        lcd_writeByte(0x00,1);
    }
}
// 显示字节定位
// x: x轴坐标 0-83
// y: y轴坐标 0-5
void lcd_pos_byte(u8 x,u8 y){
    x |= X_Col_addr;
    y |= Y_Row_addr;
    lcd_writeByte(x,0);
    lcd_writeByte(y,0);
}
// 清屏 某一行
void lcd_clear_row(u8 rowNum){
    u8 i;
    lcd_pos_byte(0,rowNum);
    for(i = 0; i < 84; i ++){
        lcd_writeByte(0x00,1);
    }
}
// 显示一个6*8字符
void lcd_show_char(u8 x, u8 y, u8 c_dat){
    u8 i;
    c_dat -= 32;
    x *= 6;
    lcd_pos_byte(x,y);
    for(i = 0; i < 6; i ++){
        lcd_writeByte(Font_[c_dat][i],1);
    }
}
// 显示字符串
void lcd_show_string(u8 x, u8 y, char *str){
    while(*str){
        lcd_show_char(x++, y, *str);
        str ++;
        if(x == 14){ x = 0; y ++;}
        if(y == 6){ y = 0;}
    }
}
// 初始化液晶
void lcd_init(){
    gpioInit();
    int isOK = wiringPiSPISetup(0, 1000000);
    if (isOK == -1) {
        printf("SPI设置失败\n");
    }
    else {
        printf("SPI设置OK == %d\n",isOK);
    }
    digitalWrite(LCD_RST,LOW); // 液晶复位
    delay(20);
    digitalWrite(LCD_RST,HIGH);
    delay(20);
    lcd_writeByte(0x21,0); // 工作模式 水平寻址  扩展指令
    lcd_writeByte(0x06,0); // VLCD温度系数2
    lcd_writeByte(0x13,0); // 设置偏置系统 1:48
    lcd_writeByte(0xc8,0); // 设置对比度
    lcd_writeByte(0x20,0); // 工作模式 水平寻址 常规指令
    lcd_writeByte(0x0c,0); // 普通模式
    lcd_writeByte(X_Col_addr,0);
    lcd_writeByte(Y_Row_addr,0); 
    lcd_clear(); // 清屏
}

int main (void)
{
    wiringPiSetup();
    lcd_init();
    lcd_show_string(0,0,"I Love You!");
	return 0;
}

相关函数说明

void lcd_show_char(u8 x, u8 y, u8 c_dat)出现了32和6这个两个数字,这里说明一下:

  1. 32:在上面的数组Font_[][6]中,我们可以看见字符0书数组的第16个元素,而字符0的ASCII(百度百科)码是48,所以48-32之后就是16,也就是字符0在数组Font_[][6]的位置。其他的字符依次内推。
  2. 6:每个字符的大小是一个6*8的点阵,NOKIA5110液晶是一个84*48的点阵屏,也就是在X轴方向第一个字符和第二个字符之间相隔6个单位,所以是乘以6。
    那么在这个函数void lcd_show_string(u8 x, u8 y, char *str)中出现时14就很好解释了,84除以6也就是14了。
    这连个函数中的参数xy的取值范围也是0-130-5,也就是说一行最多显示14个字符,最多显示6行,每个字符的大小都是6*8
    关于上面的数组Font_[][6]中字符0的编码为什么是0x00,0x3E,0x51,0x49,0x45,0x3E,这个我觉得大家可以画一个6*8的点阵格子,把字符0画出来,然后每一列从上往下编码,颜色深的是1,空白是0,然后转成16进制,就是上面的结果了。如果你玩过点阵,请忽略这里。如果你用过字符取模软件,请忽略这里。

显示效果图

为什么拍照,我把背光给关闭了。
在这里插入图片描述

已标记关键词 清除标记
import com.pi4j.wiringpi.Spi; public class WiringPiSPIExample { // SPI operations public static byte WRITE_CMD = 0x40; public static byte READ_CMD = 0x41; @SuppressWarnings("unused") public static void main(String args[]) throws InterruptedException { // // This SPI example is using the WiringPi native library to communicate with // the SPI hardware interface connected to a MCP23S17 I/O Expander. // // Please note the following command are required to enable the SPI driver on // your Raspberry Pi: // > sudo modprobe spi_bcm2708 // > sudo chown `id -u`.`id -g` /dev/spidev0.* // // this source code was adapted from: // https://github.com/thomasmacpherson/piface/blob/master/python/piface/pfio.py // // see this blog post for additional details on SPI and WiringPi // http://wiringpi.com/reference/spi-library/ // // see the link below for the data sheet on the MCP23S17 chip: // http://ww1.microchip.com/downloads/en/devicedoc/21952b.pdf System.out.println("<--Pi4J--> SPI test program using MCP23S17 I/O Expander Chip"); // configuration byte IODIRA = 0x00; // I/O direction A byte IODIRB = 0x01; // I/O direction B byte IOCON = 0x0A; // I/O config byte GPIOA = 0x12; // port A byte GPIOB = 0x13; // port B byte GPPUA = 0x0C; // port A pullups byte GPPUB = 0x0D; // port B pullups byte OUTPUT_PORT = GPIOA; byte INPUT_PORT = GPIOB; byte INPUT_PULLUPS = GPPUB; // setup SPI for communication int fd = Spi.wiringPiSPISetup(0, 10000000); if (fd <= -1) { System.out.println(" ==>> SPI SETUP FAILED"); return; } // initialize write(IOCON, 0x08); // enable hardware addressing write(GPIOA, 0x00); // set port A off write(IODIRA, 0); // set port A as outputs write(IODIRB, 0xFF); // set port B as inputs write(GPPUB, 0xFF); // set port B pullups on int pins = 1; // infinite loop while(true) { // shift the bit to the left in the A register // this will cause the next LED to light up and // the current LED to turn off. if(pins >= 255) pins=1; write(GPIOA, (byte)pins); pins = pins << 1; Thread.sleep(1000); // read for input changes //read(INPUT_PORT); } } public static void write(byte register, int data){ // send test ASCII message byte packet[] = new byte[3]; packet[0] = WRITE_CMD; // address byte packet[1] = register; // register byte packet[2] = (byte)data; // data byte System.out.println("-----------------------------------------------"); System.out.println("[TX] " + bytesToHex(packet)); Spi.wiringPiSPIDataRW(0, packet, 3); System.out.println("[RX] " + bytesToHex(packet)); System.out.println("-----------------------------------------------"); } public static void read(byte register){ // send test ASCII message byte packet[] = new byte[3]; packet[0] = READ_CMD; // address byte packet[1] = register; // register byte packet[2] = 0b00000000; // data byte System.out.println("-----------------------------------------------"); System.out.println("[TX] " + bytesToHex(packet)); Spi.wiringPiSPIDataRW(0, packet, 3); System.out.println("[RX] " + bytesToHex(packet)); System.out.println("-----------------------------------------------"); } public static String bytesToHex(byte[] bytes) { final char[] hexArray = {&#39;0&#39;,&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,&#39;4&#39;,&#39;5&#39;,&#39;6&#39;,&#39;7&#39;,&#39;8&#39;,&#39;9&#39;,&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;}; char[] hexChars = new char[bytes.length * 2]; int v; for ( int j = 0; j < bytes.length; j++ ) { v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } } ``` 代码神码意思 ```
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页