linux SPI操作LCD12864液晶
液晶型号为JLX12864 COG液晶,资料网上有,linux下面通过SPI与IO控制,IO控制使用的是文件方式,SPI是开发板提供的驱动,这个SPI驱动应该每家提供的都不一样,需要自己去按照驱动文档操作,主要不通电就是底层的配置不一样。//SPI.c这个是打开SPI驱动/** SPI.c**Created on: 2018年8月2日*Author: cf...
·
液晶型号为JLX12864 COG液晶,资料网上有,linux下面通过SPI与IO控制,IO控制使用的是文件方式,SPI是开发板提供的驱动,这个SPI驱动应该每家提供的都不一样,需要自己去按照驱动文档操作,主要不通电就是底层的配置不一样。
//SPI.c这个是打开SPI驱动
/*
* SPI.c
*
* Created on: 2018年8月2日
* Author: cfan
*/
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <termios.h>
#include "SPI.h"
#include <errno.h> // 包含errno所需要的头文件
#include <string.h> // 包含strerror所需要的头文件
#include "typedef.h"
//SPI初始化
int SPI_Init(SPI_HANDLE *pHandle, const char *pSpiDeviceName)
{
pHandle->fd = -1;
if(pSpiDeviceName == NULL || pHandle==NULL || strlen(pSpiDeviceName)>SPI_DEVICE_NAME_MAX_LEN)
{
printf("%s(%d)Check the input parameters!\r\n",__FILE__ , __LINE__);
return -1;
}
strcpy(pHandle->SpiDeviceName, pSpiDeviceName); //记录串口设备名称
//打开SPI
pHandle->fd = open(pSpiDeviceName, O_RDWR|O_NOCTTY|O_NDELAY); //读写独占方式打开SPI
if (pHandle->fd < 0)
{
//打印错误信息
printf("Can't Open SPI(%s) : %s(%d)\n",pSpiDeviceName, strerror(errno), errno);
return errno;
}
else
{
printf("Open SPI OK!\r\n");
}
return 0;
}
//spi.h
/*
* SPI.h
*
* Created on: 2018年8月2日
* Author: cfan
*/
#ifndef HARDWARE_SPI_H_
#define HARDWARE_SPI_H_
#include "termios.h"
#include "typedef.h"
#define SPI_DEVICE_NAME_MAX_LEN 35 //SPI名称最大长度
//SPI接口句柄
typedef struct
{
int fd;
char SpiDeviceName[SPI_DEVICE_NAME_MAX_LEN+1]; //SPI名称
}SPI_HANDLE;
//SPI初始化
int SPI_Init(SPI_HANDLE *pHandle, const char *pSpiDeviceName);
#endif /* HARDWARE_SPI_H_ */
//SPI驱动调用,这个是开发板提供的,各个厂家应该都不一样,需要自己去查询
#include "common.h"
#include "spi_enum.h"
#include "spidev.h"
#include <sys/ioctl.h>
#include "nano_pi_spi.h"
//开发板官方提供的SPI驱动接口
#define SPI_MAX_SPEED 25000000 //最大时钟速度
/*************************************************************************************************************************
*函数 : int setSPIWriteBitsPerWord(int spi_fd, int bits)
*功能 : 设置每次读SPI设备的字长,单位是比特.
*参数 : spi_fd: SPI设备的文件描述符;bits: 字长,单位是比特
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 : 虽然大部分SPI接口的字长是8或者16,仍然会有一些特殊的例子。
需要说明的是,如果这个成员为零的话,默认使用8作为字长(ioctl SPI_IOC_WR_BITS_PER_WORD)
*************************************************************************************************************************/
int setSPIWriteBitsPerWord(int spi_fd, int bits)
{
clearLastError();
int ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_WR_BITS_PER_WORD");
}
return ret;
}
/*************************************************************************************************************************
*函数 : int setSPIReadBitsPerWord(int spi_fd, int bits)
*功能 : 设置每次写SPI设备的字长,单位是比特
*参数 : spi_fd: SPI设备的文件描述符;bits: 字长,单位是比特
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 : 虽然大部分SPI接口的字长是8或者16,仍然会有一些特殊的例子。
需要说明的是,如果这个成员为零的话,默认使用8作为字长(ioctl SPI_IOC_WR_BITS_PER_WORD)
*************************************************************************************************************************/
int setSPIReadBitsPerWord(int spi_fd, int bits)
{
int ret = ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
clearLastError();
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_RD_BITS_PER_WORD");
}
return ret;
}
/*************************************************************************************************************************
*函数 : int setSPIBitOrder(int spi_fd, int order)
*功能 : 设备SPI传输时是先传输低比特位还是高比特位
*参数 : spi_fd: SPI设备的文件描述符;order: 传SPIEnum.MSBFIRST或SPIEnum.LSBFIRST
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 : 可选的参数有SPIEnum.MSBFIRST和SPIEnum.LSBFIRST
*************************************************************************************************************************/
int setSPIBitOrder(int spi_fd, int order)
{
int ret;
int spi_mode = 0;
clearLastError();
if(order == LSBFIRST) {
spi_mode |= SPI_LSB_FIRST;
} else {
spi_mode &= ~SPI_LSB_FIRST;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_WR_MODE");
return ret;
}
return ret;
}
/*************************************************************************************************************************
*函数 : int setSPIMaxSpeed(int spi_fd, unsigned int spi_speed)
*功能 : 设备SPI传输速度
*参数 : spi_fd: SPI设备的文件描述符;spi_speed: 速度(分频,越小速度越高)
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int setSPIMaxSpeed(int spi_fd, unsigned int spi_speed)
{
int ret;
unsigned int realSpeed;
clearLastError();
if (spi_speed<0 || spi_speed>SPI_MAX_SPEED) {
setLastError("invalid spi speed %d", spi_speed);
}
ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_WR_MAX_SPEED_HZ");
return ret;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &realSpeed);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_RD_MAX_SPEED_HZ");
return ret;
}
return ret;
}
/*************************************************************************************************************************
*函数 : int setSPIDataMode(int spi_fd, int mode)
*功能 : 设置SPI设备的模式
*参数 : spi_fd: SPI设备的文件描述符;mode: SPI设备的模式,可传入SPI_MODE0 ~ SPI_MODE3
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int setSPIDataMode(int spi_fd, int mode)
{
int ret;
int spi_mode = 0;
clearLastError();
switch(mode) {
case SPI_MODE0:
spi_mode &= ~(SPI_CPHA|SPI_CPOL);
break;
case SPI_MODE1:
spi_mode &= ~(SPI_CPOL);
spi_mode |= (SPI_CPHA);
break;
case SPI_MODE2:
spi_mode |= (SPI_CPOL);
spi_mode &= ~(SPI_CPHA);
break;
case SPI_MODE3:
spi_mode |= (SPI_CPHA|SPI_CPOL);
break;
default:
setLastError("error SPIDataMode");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_WR_MODE");
return ret;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MODE, &mode);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_RD_MODE");
return ret;
}
return ret;
}
/*************************************************************************************************************************
*函数 : int SPItransferOneByte(int spi_fd, unsigned char byteData, int spi_delay, int spi_speed, int spi_bits)
*功能 : 同时发送与接收一个字节的数据
*参数 : spi_fd: SPI设备的文件描述符;byteData:要写入SPI设备的数据;spi_delay:延时;spi_speed:传输速度;spi_bits:字长,单位是比特
*返回 : 成功返回读到的数据,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int SPItransferOneByte(int spi_fd , unsigned char byteData, int spi_delay, int spi_speed, int spi_bits)
{
int ret;
unsigned char tx[1] = {0};
unsigned char rx[1] = {0};
tx[0] = byteData;
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
tr.len = 1;
tr.delay_usecs = spi_delay;
tr.speed_hz = spi_speed;
tr.bits_per_word = spi_bits;
clearLastError();
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_MESSAGE");
return ret;
}
return rx[0];
}
/*************************************************************************************************************************
*函数 : int SPItransferBytes(int spi_fd, unsigned char * writeData, int writeLen, unsigned char * readBuffer,
*函数 int readLen, int spi_delay, int spi_speed, int spi_bits)
*功能 : 同时发送与接收多个字节的数据
*参数 : spi_fd: SPI设备的文件描述符;writeData:要写入的数据;readBuff: 存放读取数据的缓冲区;spi_delay:延时;spi_speed:传输速度;
spi_bits:字长,单位是比特
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int SPItransferBytes(int spi_fd, unsigned char * writeData, int writeLen, unsigned char * readBuffer, int readLen, int spi_delay,
int spi_speed, int spi_bits)
{
unsigned int len = writeLen;
if (len > readLen) {
len = readLen;
}
unsigned char * pWriteData = writeData;
unsigned char * pReadBuffer = readBuffer;
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)pWriteData;
tr.rx_buf = (unsigned long)pReadBuffer;
tr.len = len;
tr.delay_usecs = spi_delay;
tr.speed_hz = spi_speed;
tr.bits_per_word = spi_bits;
int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
clearLastError();
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_MESSAGE");
}
return ret;
}
/*************************************************************************************************************************
*函数 : int writeBytesToSPI(int spi_fd, unsigned char * writeData, int writeLen, int spi_delay, int spi_speed,
*函数 int spi_bits)
*功能 : 写多个字节的数据到SPI设 备
*参数 : spi_fd: SPI设备的文件描述符;writeData:要写入的数据;spi_delay:延时;spi_speed:传输速度;spi_bits:字长,单位是比特
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int writeBytesToSPI(int spi_fd, unsigned char * writeData, int writeLen, int spi_delay, int spi_speed, int spi_bits)
{
unsigned int len = writeLen;
unsigned char * pWriteData = writeData;
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)pWriteData;
tr.rx_buf = (unsigned long)0;
tr.len = len;
tr.delay_usecs = spi_delay;
tr.speed_hz = spi_speed;
tr.bits_per_word = spi_bits;
int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
clearLastError();
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_MESSAGE");
}
return ret;
}
/*************************************************************************************************************************
*函数 : int readBytesFromSPI(int spi_fd, unsigned char * readBuffer, int readLen, int spi_delay, int spi_speed,
*函数 int spi_bits)
*功能 : 从SPI设备读取多个字节
*参数 : spi_fd: SPI设备的文件描述符;readBuff: 存放读取数据的缓冲区;readLen:读取长度(不能超过缓冲区大小)
spi_delay:延时;spi_speed:传输速度;spi_bits:字长,单位是比特
*返回 : 成功返回0,失败返回负数
*依赖 : 无
*作者 : Friendly NanoPI-NEO(cp1300@139.com整理)
*时间 : 2018-08-12
*最后修改时间 : 2018-08-12
*说明 :
*************************************************************************************************************************/
int readBytesFromSPI(int spi_fd, unsigned char * readBuffer, int readLen, int spi_delay, int spi_speed, int spi_bits)
{
unsigned int len = readLen;
unsigned char * pReadBuffer = readBuffer;
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)0;
tr.rx_buf = (unsigned long)pReadBuffer;
tr.len = len;
tr.delay_usecs = spi_delay;
tr.speed_hz = spi_speed;
tr.bits_per_word = spi_bits;
int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
clearLastError();
if (ret < 0) {
setLastError("Can't ioctl SPI_IOC_MESSAGE");
}
return ret;
}
//JLX12864G.c 液晶硬件底层操作
/*************************************************************************************************************
* 文件名: JLX12864G.c
* 功能: JLX12864G-0088 JLX12864G液晶驱动
* 作者: cp1300@139.com
* 邮箱: cp1300@139.com
* 创建时间: 2012年5月30日20:40
* 最后修改时间:2012年5月30日
* 详细: 2016-02-01:增加获取显存函数
*************************************************************************************************************/
#include "ascii_8x16.h"
#include "JLX12864G.H"
#include <stdio.h>
#include "typedef.h"
//字模取模方式:阴码,列行式,逆向(低位在前)
//汉字支持
#define CHINESE_ENABLE 0
#if LCD_BUFF_ENABLE //使能了显存
//获取显存地址
//2016-02-01:增加获取显存函数
u8 *JLX12864G_GetGramBuff(JLX12864G_HANDLE *pHandle)
{
return (u8 *)&pHandle->LCD_BUFF[0][0];
}
#endif
/*************************************************************************************************************************
* 函数 : void JLX12864G_WriteCommand(JLX12864G_HANDLE *pHandle, u8 cmd)
* 功能 : 向JLX12864G写入一字节命令
* 参数 : pHandle:句柄;cmd:命令
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120530
* 最后修改时间 : 2018-08-12
* 说明 : RS=0,时钟上升沿数据有效,先发送高位
*************************************************************************************************************************/
void JLX12864G_WriteCommand(JLX12864G_HANDLE *pHandle, u8 cmd)
{
pHandle->SetRS(0); //RS=0
pHandle->WriteData(&cmd, 1); //发送数据
pHandle->SetRS(1); //RS=1
}
/*************************************************************************************************************************
* 函数 : static void JLX12864G_SetPageAdd(JLX12864G_HANDLE *pHandle, u8 PageAdd)
* 功能 : 设置光标页地址
* 参数 : pHandle:句柄;PageAdd:页地址,0-7
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 20120531
* 说明 : 共64行,没8行为一页,共8页
*************************************************************************************************************************/
static void JLX12864G_SetPageAdd(JLX12864G_HANDLE *pHandle, u8 PageAdd)
{
JLX12864G_WriteCommand(pHandle, 0xb0 + PageAdd);
}
/*************************************************************************************************************************
* 函数 : static void JLX12864G_SetLineAdd(JLX12864G_HANDLE *pHandle, u8 LineAdd)
* 功能 : 设置光标列地址
* 参数 : pHandle:句柄;LineAdd:列地址,0-127
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 20120531
* 说明 : 共128列
*************************************************************************************************************************/
static void JLX12864G_SetLineAdd(JLX12864G_HANDLE *pHandle, u8 LineAdd)
{
LineAdd += JLX12864G_X_OFFSET;
JLX12864G_WriteCommand(pHandle, 0x10 + (LineAdd >> 4)); //列地址高4位
JLX12864G_WriteCommand(pHandle, 0x00 + (LineAdd & 0x0f)); //列地址低4位
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_ClearAll(JLX12864G_HANDLE *pHandle)
* 功能 : JLX12864G液晶清屏
* 参数 : pHandle:句柄;
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120530
* 最后修改时间 : 20120530
* 说明 : 无
*************************************************************************************************************************/
void JLX12864G_ClearAll(JLX12864G_HANDLE *pHandle)
{
u8 i,j;
u32 data = 0;
for(i = 0;i < 9;i ++)
{
JLX12864G_SetPageAdd(pHandle, i);
JLX12864G_SetLineAdd(pHandle, 0);
for(j = 0;j < 132/4;j ++)
{
pHandle->WriteData((u8 *)&data, 4);
}
}
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_FillAll(JLX12864G_HANDLE *pHandle)
* 功能 : JLX12864G液晶填充
* 参数 : pHandle:句柄;
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120530
* 最后修改时间 : 20120530
* 说明 : 无
*************************************************************************************************************************/
void JLX12864G_FillAll(JLX12864G_HANDLE *pHandle)
{
u8 i,j;
u32 data = 0xffffffff;
for(i = 0;i < 9;i ++)
{
JLX12864G_SetPageAdd(pHandle, i);
JLX12864G_SetLineAdd(pHandle, 0);
for(j = 0;j < 132/4;j ++)
{
pHandle->WriteData((u8 *)&data, 4);
}
}
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_ShowOneChar(JLX12864G_HANDLE *pHandle,u8 PageAdd,u8 LineAdd,u8 CHAR,u8 FontSize)
* 功能 : 在指定位置显示一个字符
* 参数 : pHandle:句柄;PageAdd:页,0~7,共8页;L:0~127共128列,CHAR:需要显示的字符,FontSize:字体大小
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120530
* 最后修改时间 : 20120530
* 说明 : 显示一个ASCII字符
*************************************************************************************************************************/
void JLX12864G_ShowOneChar(JLX12864G_HANDLE *pHandle,u8 PageAdd,u8 LineAdd,u8 CHAR,u8 FontSize)
{
u8 i,j,k;
const unsigned char *p;
CHAR -= 32;
if(CHAR > ASCII_MAX - 1)
return;
if(FontSize == 12)
p = ASCII_8X12[CHAR]; //12号
else
p = ASCII_8X16[CHAR]; //16号
for(i = 0;i < 2;i ++)
{
JLX12864G_SetPageAdd(pHandle, PageAdd + i);
JLX12864G_SetLineAdd(pHandle, LineAdd);
k = i * 8;
pHandle->WriteData((u8 *)&p[k+j], 8);
/*for(j = 0;j < 8;j ++)
{
pHandle->WriteByteData(p[k+j]);
}*/
}
}
/*************************************************************************************************************************
* 函数 : void LCD_PrintfChar(JLX12864G_HANDLE *pHandle,u8 PageAdd,u8 LineAdd,const char *p,u8 FontSize)
* 功能 : 在指定位置显示字符串
* 参数 : pHandle:句柄;PageAdd:页,0~7,共8页;L:0~127共128列;p:字符指针,FontSize:子大小;16或者12
* 返回 : 无
* 依赖 : JLX12864G_ShowOneChar
* 作者 : cp1300@139.com
* 时间 : 20120601
* 最后修改时间 : 20120601
* 说明 : FontSize = 16或者 12
*************************************************************************************************************************/
void JLX12864G_PrintfChar(JLX12864G_HANDLE *pHandle,u8 PageAdd,u8 LineAdd,const char *p,u8 FontSize)
{
while(*p != 0)
{
JLX12864G_ShowOneChar(pHandle, PageAdd,LineAdd,*p,FontSize);
p ++;
LineAdd += 8;
}
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_SetConAdj(JLX12864G_HANDLE *pHandle,u8 cont)
* 功能 : 设置液晶的对比度
* 参数 : pHandle:句柄;cont:对比度值
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2014-08-24
* 最后修改时间 : 2014-08-24
* 说明 : 需要先初始化LCD
*************************************************************************************************************************/
void JLX12864G_SetConAdj(JLX12864G_HANDLE *pHandle,u8 cont)
{
if(cont < 25)cont = 25;
if(cont > 60)cont = 60;
JLX12864G_WriteCommand(pHandle, 0x81); /*微调对比度*/
JLX12864G_WriteCommand(pHandle, cont); /*微调对比度的值,可设置范围0~63*/
pHandle->LCD_Cont = cont; //更新对比度
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_Init(JLX12864G_HANDLE *pHandle,
void (*WriteData)(u8 data,u8 len), //写数据接口
void (*SetRS)(u8 level), //设置RS电平
void (*SetRST)(u8 level), //设置RST电平
void (*DelayMS)(u8 ms), //ms延时
u8 LCDCont)
* 功能 : 初始化JLX12864G液晶
* 参数 : pHandle:句柄;WriteByteData:写一字节函数;SetRS:设置RS电平;SetRST:设置RST电平;DelayMS:系统ms延时;LCDCont:对比度
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120530
* 最后修改时间 : 2018-08-12
* 说明 : 初始化JLX12864G液晶
*************************************************************************************************************************/
void JLX12864G_Init(JLX12864G_HANDLE *pHandle,
void (*WriteData)(u8 *data,u8 len), //写数据接口
void (*SetRS)(u8 level), //设置RS电平
void (*SetRST)(u8 level), //设置RST电平
void (*DelayMS)(u8 ms), //ms延时
u8 LCDCont)
{
if(pHandle == NULL)
{
printf("JLX12864G:ERROR *pHandle is NULL!\r\n");
return;
}
if(WriteData == NULL)
{
printf("JLX12864G:ERROR *WriteData is NULL!\r\n");
return;
}
if(SetRS == NULL)
{
printf("JLX12864G:ERROR *SetRS is NULL!\r\n");
return;
}
if(DelayMS == NULL)
{
printf("JLX12864G:ERROR *DelayMS is NULL!\r\n");
return;
}
pHandle->WriteData = WriteData;
pHandle->SetRS = SetRS;
pHandle->SetRST = SetRST;
pHandle->DelayMS = DelayMS;
if(pHandle->SetRST != NULL)
{
pHandle->SetRST(0);//液晶复位开始
pHandle->DelayMS(1);
pHandle->SetRST(1);//液晶复位结束
}
pHandle->DelayMS(1);
JLX12864G_WriteCommand(pHandle, 0xe2); /*软复位*/
JLX12864G_WriteCommand(pHandle, 0x2c); /*升压步聚1*/
JLX12864G_WriteCommand(pHandle, 0x2e); /*升压步聚2*/
JLX12864G_WriteCommand(pHandle, 0x2f); /*升压步聚3*/
JLX12864G_WriteCommand(pHandle, 0x23); /*粗调对比度,可设置范围20~27*/
// JLX12864G_WriteCommand(0x81); /*微调对比度*/
// JLX12864G_WriteCommand(0x30); /*微调对比度的值,可设置范围0~63*/
JLX12864G_SetConAdj(pHandle, LCDCont);
JLX12864G_WriteCommand(pHandle, 0xa2); /*1/9 偏压比(bias)*/
#if(LCD_ROTATE_180) //旋转180度显示
JLX12864G_WriteCommand(pHandle, 0xc0); /*行扫描顺序:从下到上*/
JLX12864G_WriteCommand(pHandle, 0xa1); /*列扫描顺序:从右到左*/
#else
JLX12864G_WriteCommand(pHandle, 0xc8); /*行扫描顺序:从上到下*/
JLX12864G_WriteCommand(pHandle, 0xa0); /*列扫描顺序:从左到右*/
#endif
JLX12864G_WriteCommand(pHandle, 0x40); //初始化显示行为0
JLX12864G_WriteCommand(pHandle, 0xa4); //常规显示
JLX12864G_WriteCommand(pHandle, 0xaf); /*开显示*/
JLX12864G_ClearAll(pHandle);
pHandle->LCD_Cont = LCDCont;
//isPowerStatus = TRUE; //上电完成
}
/*************************************************************************************************************************
* 函数 : void JLX12864G_GRAM_Up(JLX12864G_HANDLE *pHandle, u8 LCD_BUFF[8][128], u8 x1,u8 y1,u8 x2,u8 y2)
* 功能 : 更新显存至液晶
* 参数 : pHandle:句柄;LCD_BUFF:显存地址;x1,y1:起始坐标;x2,y2:终点坐标
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 2018-08-12
* 说明 : y坐标会页对齐
*************************************************************************************************************************/
void JLX12864G_GRAM_Up(JLX12864G_HANDLE *pHandle, u8 LCD_BUFF[8][128], u8 x1,u8 y1,u8 x2,u8 y2)
{
u8 i,j;
if(x2 > 127) x2 = 127;
y1 /= 8; //计算页地址
y2 /= 8;
for(i = 0;i < (y2 - y1 + 1);i ++)
{
JLX12864G_SetPageAdd(pHandle, y1 + i); //写入页地址
JLX12864G_SetLineAdd(pHandle, x1); //写入行地址
pHandle->WriteData(&LCD_BUFF[y1 + i][x1 + 0], (x2 - x1 + 1));
/*for(j = 0;j < (x2 - x1 + 1);j ++)
{
LCD12864_WriteData(pHandle, LCD_BUFF[y1 + i][x1 + j]);
}*/
}
}
//LCD12864.c 这个是个内存中的虚拟LCD,每次操作都在内存中操作,然后同步到实际LCD
/*
* LCD12864_Virtual.c
* 虚拟LCD12864
* Created on: 2018年8月12日
* Author: cfan
*/
#include "LCD12864.h"
#include "typedef.h"
#include "ASCII_8x16.h"
#include <stdio.h>
#include <string.h>
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_Init(LCD12864_HANDLE *pHandle)
* 功能 : LCD12864显存模式初始化
* 参数 : pHandle:句柄;
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_Init(LCD12864_HANDLE *pHandle)
{
if(pHandle == NULL)
{
printf("LCD12864:ERROR *pHandle is NULL!\r\n");
return;
}
memset(pHandle->LCD_BUFF, 0, 8*128);
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_DrawPoint(LCD12864_HANDLE *pHandle, u8 x,u8 y)
* 功能 : 在显存里面指定位置画点
* 参数 : pHandle:句柄;x:X坐标,0-127;y:y坐标,0-63
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_DrawPoint(LCD12864_HANDLE *pHandle, u8 x,u8 y)
{
if(x > 127 || y > 63)
return;
pHandle->LCD_BUFF[y / 8][x] |= (1 << (y % 8));
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_ClearPoint(LCD12864_HANDLE *pHandle, u8 x,u8 y)
* 功能 : 擦除显存里面指定位置的点
* 参数 : pHandle:句柄;x:X坐标,0-127;y:y坐标,0-63
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_ClearPoint(LCD12864_HANDLE *pHandle, u8 x, u8 y)
{
if(x > 127 || y > 63)
return;
pHandle->LCD_BUFF[y / 8][x] &= ~(1 << (y % 8));
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_ClearAll(LCD12864_HANDLE *pHandle)
* 功能 : 清除全部显存
* 参数 : pHandle:句柄;
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 20120531
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_ClearAll(LCD12864_HANDLE *pHandle)
{
u8 i,j;
for(i = 0;i < 8;i ++)
{
for(j = 0;j < 128;j ++)
{
pHandle->LCD_BUFF[i][j] = 0x00;
}
}
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_ShowChar(LCD12864_HANDLE *pHandle, u8 x,u8 y,u8 CHAR,LCD12864_FONT_MODE FontMode)
* 功能 : 在指定位置显示一个指定大小的字符
* 参数 : pHandle:句柄;x,y:显示开始坐标,p:汉子点阵缓冲区;FontMode:汉子显示模式,
* 返回 : 无
* 依赖 : 画点函数
* 作者 : cp1300@139.com
* 时间 : 20120603
* 最后修改时间 : 2018-08-12
* 说明 :
*************************************************************************************************************************/
void LCD12864_GRAM_ShowChar(LCD12864_HANDLE *pHandle, u8 x,u8 y,u8 CHAR,LCD12864_FONT_MODE FontMode)
{
u8 i,j;
u8 FontSize = (u8)FontMode&0x0f; //获取字体大小
u8 *p;
void (*DrawPoint)(LCD12864_HANDLE *pHandle, u8 i,u8 j);
void (*ClearPoint)(LCD12864_HANDLE *pHandle, u8 i,u8 j);
CHAR -= 32;
if(CHAR > 95 - 1) //限制ASCII范围
return;
if(FontSize)
{
FontSize = 12;
p = (u8 *)ASCII_8X12[CHAR]; //12号
}
else
{
FontSize = 16;
p = (u8 *)ASCII_8X16[CHAR]; //16号
}
if(FontMode & 0x40) //反显
{
DrawPoint = LCD12864_GRAM_ClearPoint;
ClearPoint = LCD12864_GRAM_DrawPoint;
}
else //正常模式
{
ClearPoint = LCD12864_GRAM_ClearPoint;
DrawPoint = LCD12864_GRAM_DrawPoint;
}
if(FontMode & 0x80) //叠加显示
{
for(j = 0;j < 8;j ++)
{
for(i = 0;i < 8;i ++)
{
if(*p & (1 << i))
(*DrawPoint)(pHandle, x + j,y + i);
}
p ++;
}
for(j = 0;j < 8;j ++)
{
for(i = 0;i < FontSize - 8;i ++)
{
if(*p & (1 << i))
(*DrawPoint)(pHandle, x + j,y + 8 + i);
}
p ++;
}
}
else //非叠加显示
{
for(j = 0;j < 8;j ++)
{
for(i = 0;i < 8;i ++)
{
if(*p & (1 << i))
(*DrawPoint)(pHandle, x + j,y + i);
else
(*ClearPoint)(pHandle, x + j,y + i);
}
p ++;
}
for(j = 0;j < 8;j ++)
{
for(i = 0;i < FontSize - 8;i ++)
{
if(*p & (1 << i))
(*DrawPoint)(pHandle, x + j,y + 8 + i);
else
(*ClearPoint)(pHandle, x + j,y + 8 + i);
}
p ++;
}
}
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_Fill(LCD12864_HANDLE *pHandle, u16 xStart, u16 yStart, u16 xEnd, u16 yEnd)
* 功能 : 指定位置填充
* 参数 : pHandle:句柄;范围
* 返回 : 无
* 依赖 : 底层函数
* 作者 : cp1300@139.com
* 时间 : 20110920
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_Fill(LCD12864_HANDLE *pHandle, u16 xStart, u16 yStart, u16 xEnd, u16 yEnd)
{
u16 i,j;
for(i = xStart;i < xEnd; i ++)
{
for(j = yStart;j < yEnd;j ++)
{
LCD12864_GRAM_DrawPoint(pHandle,i,j);
}
}
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_Clear(LCD12864_HANDLE *pHandle, u16 xStart, u16 yStart, u16 xEnd, u16 yEnd)
* 功能 : 清除指定位置
* 参数 : pHandle:句柄;范围
* 返回 : 无
* 依赖 : 底层函数
* 作者 : cp1300@139.com
* 时间 : 20110920
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_Clear(LCD12864_HANDLE *pHandle, u16 xStart, u16 yStart, u16 xEnd, u16 yEnd)
{
u16 i,j;
for(i = xStart;i < xEnd; i ++)
{
for(j = yStart;j < yEnd;j ++)
{
LCD12864_GRAM_ClearPoint(pHandle,i,j);
}
}
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_DrawLine(LCD12864_HANDLE *pHandle,u16 x1, u16 y1, u16 x2, u16 y2)
* 功能 : 画线函数
* 参数 : pHandle:句柄;起点终点坐标
* 返回 : 无
* 依赖 : 画点函数
* 作者 : cp1300@139.com
* 时间 : 20110920
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_DrawLine(LCD12864_HANDLE *pHandle,u16 x1, u16 y1, u16 x2, u16 y2)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
//TFT_LCD_SetRamAddr(0,239,0,319);//设置显示窗口
delta_x=x2-x1; //计算坐标增量
delta_y=y2-y1;
uRow=x1;
uCol=y1;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
LCD12864_GRAM_DrawPoint(pHandle, uRow,uCol);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_DrawRectangle(LCD12864_HANDLE *pHandle,u16 x1, u16 y1, u16 x2, u16 y2)
* 功能 : 在指定位置画一个矩形
* 参数 : pHandle:句柄;多边形的两个坐标
* 返回 : 无
* 依赖 : 画线函数
* 作者 : cp1300@139.com
* 时间 : 20110920
* 最后修改时间 : 2018-08-12
* 说明 : 无
*************************************************************************************************************************/
void LCD12864_GRAM_DrawRectangle(LCD12864_HANDLE *pHandle,u16 x1, u16 y1, u16 x2, u16 y2)
{
LCD12864_GRAM_DrawLine(pHandle, x1,y1,x2,y1);
LCD12864_GRAM_DrawLine(pHandle, x1,y1,x1,y2);
LCD12864_GRAM_DrawLine(pHandle, x1,y2,x2,y2);
LCD12864_GRAM_DrawLine(pHandle, x2,y1,x2,y2);
}
/*************************************************************************************************************************
* 函数 : void LCD12864_GRAM_ShowString(LCD12864_HANDLE *pHandle, u16 x,u16 y,const char *pStr,LCD12864_FONT_MODE Font_MODE)
* 功能 : 在显存指定位置显示字符串
* 参数 : pHandle:句柄;x,y:显示开始坐标,pStr:字符串缓冲区;FontMode:显示模式,
* 返回 : 无
* 依赖 : 画点函数
* 作者 : cp1300@139.com
* 时间 : 2014-08-20
* 最后修改时间 : 2018-08-12
* 说明 :
*************************************************************************************************************************/
void LCD12864_GRAM_ShowString(LCD12864_HANDLE *pHandle, u16 x,u16 y,const char *pStr,LCD12864_FONT_MODE Font_MODE)
{
u8 Font_Size = Font_MODE & 0x0f;
#if CHINESE_ENABLE
u8 buff[32];
#endif
while(*pStr != 0)
{
#if CHINESE_ENABLE
if(*pStr > 0x80)//汉字
{
FONT_GetFontLattice(buff, (u8*)pStr, ST16X16); //获取汉字点阵
LCD12864_GRAM_ShowChina(x,y,buff,Font_MODE); //显示汉字
pStr += 2;
if(x > 127 - 16) //自动换行
{
x = 0;
y += 16;
}
else
{
x += 16;
}
}
else //ASCII
#endif
{
LCD12864_GRAM_ShowChar(pHandle, x,y,*pStr,Font_MODE);
pStr++;
if(x > 127 - 8) //自动换行
{
x = 0;
y += Font_Size;
}
else
{
x += 8;
}
}
}
}
//LCD12864.h
/*
* LCD12864_Virtual.h
*
* Created on: 2018年8月12日
* Author: cfan
*/
#ifndef PROGRAM_LCD_LCD12864_H_
#define PROGRAM_LCD_LCD12864_H_
#include "typedef.h"
typedef enum
{
FONT16_DEFAULT = (0x80+16), //16号,叠加显示
FONT12_DEFAULT = (0x80+12), //12号,叠加显示
FONT16_COVER = (16), //16号,覆盖显示
FONT12_COVER = (12), //12号,覆盖显示
FONT16_REVERSE = (0x40+16), //16号,反显显示
FONT12_REVERSE = (0x40+12), //12号,反显显示
}LCD12864_FONT_MODE;
//LCD12864 句柄
typedef struct
{
u8 LCD_BUFF[8][128];//显存
//void (*UpdateGRAM)(u8 LCD_BUFF[8][128], u8 x1,u8 y1,u8 x2,u8 y2);
}LCD12864_HANDLE;
void LCD12864_GRAM_Init(LCD12864_HANDLE *pHandle);//LCD12864显存模式初始化
void LCD12864_GRAM_ShowString(LCD12864_HANDLE *pHandle, u16 x,u16 y,const char *pStr,LCD12864_FONT_MODE Font_MODE); //在显存指定位置显示字符串
#endif /* PROGRAM_LCD_LCD12864_H_ */
//测试线程
//测试线程
void *func(void *arg)
{
float ftemp = 0;
char buff[64];
SPI_Init(&SPI_Handle, "/dev/spidev0.0"); //打开SPI驱动
setSPIReadBitsPerWord(SPI_Handle.fd, 8); //8bit模式
setSPIBitOrder(SPI_Handle.fd, MSBFIRST); //高位在前
//setSPIMaxSpeed(SPI_Handle.fd, 500); //设备SPI传输速度 10K
setSPIDataMode(SPI_Handle.fd, SPI_MODE0); //模式0
if(initPinGPIO(BOARD_NANOPI_M1) < 0) //初始化开发板型号
{
printf("error:gpio init error!\r\n");
}
exportGPIOPin(LCD_RST_PIN_INDEX); //导出IO文件 RST接口
setGPIODirection(LCD_RST_PIN_INDEX, GPIO_OUT); //输出
exportGPIOPin(LCD_RS_PIN_INDEX); //导出IO文件 RS接口
setGPIODirection(LCD_RS_PIN_INDEX, GPIO_OUT); //输出
//初始化JLX12864G硬件
JLX12864G_Init(&mJLX12864G_Handle, JLX12864G_WriteData, JLX12864G_SetRS, JLX12864G_SetRST, JLX12864G_DelayMS, 40);
LCD12864_GRAM_Init(&g_LCD12864_Handle); //初始化虚拟LCD12864屏幕
while(1)
{
ftemp = GetCPU_Temp(); //获取CPU温度
sprintf(buff,"CPU TEMP:%.02f",ftemp); //格式化字符串
LCD12864_GRAM_ShowString(&g_LCD12864_Handle, 0 ,0, buff, FONT16_COVER); //覆盖显示-将字符串在虚拟LCD12864中显示
JLX12864G_GRAM_Up(&mJLX12864G_Handle, g_LCD12864_Handle.LCD_BUFF, 0,0,128,64); //更新显存到JLX12864G
sleep(3);
}
}
更多推荐
已为社区贡献5条内容
所有评论(0)