Linux(二):GPIO

本文介绍了如何在NanoPi M1 Plus开发板上使用GPIO驱动友晶科技提供的OLED显示屏。首先,介绍了GPIO库的获取和编译过程,然后详细展示了C语言代码的编写,包括初始化、清屏、画点、画线、显示字符和数字等基本功能。此外,还提供了字库文件和示例测试文件的内容。整个过程旨在展示在嵌入式系统中如何控制硬件接口实现显示功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FriendlyARM官方已经提供了GPIO驱动库,只需要下载-编译即可使用。

GPIO

NanoPi M1 Plus GPIO wiki链接
在这里插入图片描述
可以看出Pi提供的接口还是比较丰富的,我将要使用其中4个GPIO点亮一个彩色OLED屏。

WiringPi安装

wiringPi库最早是由Gordon Henderson所编写并维护的一个用C语言写成的类库,除了GPIO库,还包括了I2C库、SPI库、UART库和软件PWM库等,由于wiringPi的API函数和arduino非常相似,这也使得它广受欢迎。
wiringPi库除了提供wiringPi类库及其头文件外,还提供了一个命令行工具gpio:可以用来设置和读写GPIO管脚,以方便在Shell脚本中控制GPIO管脚。

wiringPi的安装非常简单,使用默认软件源安装速度还是比较快的,不需要换源。
在这里插入图片描述
指令

git clone https://github.com/friendlyarm/WiringNP
cd WiringNP/
git checkout nanopi-m1
chmod 755 build
./build

编写C文件并编译

操作系统内置了gcc,可以快速开始编译而不需要安装编译器, 通过gcc -v命令查看版本信息。
在这里插入图片描述
通过vim编译器编辑C文件(下图中使用的vi,实测vim在操作系统中是安装了的,可以直接使用vim命令)。
官方例程

  1. 创建C文件
    在这里插入图片描述
    指令
pi@NanoPi-M1-Plus:~$ touch MyFirstCode.c			| touch 用于创建文件
pi@NanoPi-M1-Plus:~$ ls -l							| ls    用于查看文件及目录,-l是指令选项:以列表形式显示
total 8												|
drwxrwxr-x 3 pi pi 4096 Nov 25 07:33 C_Language		|
-rw-rw-r-- 1 pi pi    0 Nov 28 14:11 MyFirstCode.c	| 刚刚创建的文件
drwxrwxr-x 8 pi pi 4096 Nov 25 07:02 WiringNP		|
  1. 编辑
    在这里插入图片描述
pi@NanoPi-M1-Plus:~$ vim MyFirstCode.c	| vim 使用VIM编辑目标C文件,执行后进入VIM界面

进入VIM的默认界面
在这里插入图片描述
VIM是一种命令行模式下的编辑器,其逻辑不同于图形界面下的编辑器,特征为:鼠标基本没用,提供很多指令,三种运行模式(插入/编辑模式、命令模式、底行命令模式),其用法多变,可操作性、可拓展性极强,但是新手上手难。
对于VIM的教学视频网上很多,这里给个链接:VIM教学视频
光VIM的用法就够写个几章,目前我也是刚学会一点,就不在这写了。
在这里插入图片描述
单个文件编译没有问题,接下来就要编译OLED驱动了。

OLED驱动

  1. 创建工作目录
  2. 创建4个文件
    test.c 测试文件
    oled.c 驱动文件
    oled.h 驱动文件
    font.h 字体库
  3. 编译
  4. 运行
    Linux运行界面
    在这里插入图片描述
    实际效果
    在这里插入图片描述
    驱动源码
/**
 * @file	oled.h
 * @brief	OLED驱动头文件
 * @date	2020/11/28
 * @note	调用oled驱动只需要包含此文件即可
 */

#ifndef __OLED_H
#define __OLED_H

/* Include Files ----------------------------------------*/
#include <wiringPi.h>
#include <stdint.h>

/* Golbal Defines ---------------------------------------*/
#define LCD_W 240
#define LCD_H 240

#define SIZE            16
#define XLevelL         0x00
#define XLevelH         0x10
#define Max_Column      128
#define Max_Row         64
#define Brightness      0xFF
#define X_WIDTH         128
#define Y_WIDTH         64

//画笔颜色
#define WHITE           0xFFFF
#define BLACK           0x0000   
#define BLUE            0x001F  
#define BRED            0XF81F
#define GRED            0XFFE0
#define GBLUE           0X07FF
#define RED             0xF800
#define MAGENTA         0xF81F
#define GREEN           0x07E0
#define CYAN            0x7FFF 
#define YELLOW          0xFFE0
#define BROWN           0XBC40
#define BRRED           0XFC07
#define GRAY            0X8430
//GUI颜色
#define DARKBLUE        0X01CF
#define LIGHTBLUE       0X7D7C  
#define GRAYBLUE        0X5458
//以上三色为PANEL的颜色 
#define LIGHTGREEN      0X841F //浅绿色
#define LGRAY           0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE       0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE          0X2B12 //浅棕蓝色(选择条目的反色)

#define OLED_CMD  0    //写命令
#define OLED_DATA 1    //写数据

/* GPIO Defines -----------------------------------------*/
#define OLED_SCLK_Clr() digitalWrite(11,LOW)
#define OLED_SCLK_Set() digitalWrite(11,HIGH)

#define OLED_SDIN_Clr() digitalWrite(5,LOW)
#define OLED_SDIN_Set() digitalWrite(5,HIGH)

#define OLED_RST_Clr()  digitalWrite(4,LOW)
#define OLED_RST_Set()  digitalWrite(4,HIGH)

#define OLED_DC_Clr()   digitalWrite(1,LOW)
#define OLED_DC_Set()   digitalWrite(1,HIGH)

#define OLED_BLK_Clr()  digitalWrite(21,LOW)
#define OLED_BLK_Set()  digitalWrite(21,LOW)

/* Global Variables -------------------------------------*/
extern uint16_t BACK_COLOR; 	///< Background
extern uint16_t POINT_COLOR;	///< Draw Piont


void LCD_Writ_Bus(char dat);	///< 串行写入
void LCD_WR_DATA8(char da);		///< 8bit写入
void LCD_WR_DATA(int da);		///< 16bit写入
void LCD_WR_REG(char da);		///< 寄存器
void LCD_WR_REG_DATA(int reg, int da);	///< 寄存器写入
void Address_set(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);	///< 地址设置

/** 初始化函数 */
void LCD_Init(void);

/**
 * @brief	清屏函数
 * @param	Color:	清屏填充色
 */
void LCD_Clear(uint16_t Color);

/**
 * @brief	在指定区域内填充指定颜色
 * @note	区域大小:(xend-xsta)*(yend-ysta)
 */
void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color);


/**
 * @brief	画点
 */
void LCD_DrawPoint(uint16_t x, uint16_t y);

/**
 * @brief	画一个大点
 */
void LCD_DrawPoint_big(uint16_t x, uint16_t y);

/**
 * @brief	画线
 * @param	x1,y1: 起点坐标
 * @param	x2,y2: 终点坐标
 */
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);

/** 画矩形 */
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);

/**
 * @brief	在指定位置画一个指定大小的圆
 * @param	x , y:	中心点
 * @param	r:		半径
 */
void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r);

/**
 * @brief	在指定位置显示一个字符
 * @param 	num :	要显示的字符:" "--->"~"
 * @param	mode:	叠加方式(1)还是非叠加方式(0)
 * @note 	在指定位置显示一个字符
 */
void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint8_t mode);

/** m^n函数 */
uint32_t mypow(uint8_t m, uint8_t n);

/**
 * @brief	显示数字
 * @param	x , y:	起点坐标
 * @param	len  :	数字的位数
 * @param	color:	颜色
 * @param	num  :	数值(0~4294967295);
 */
void LCD_ShowNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len);

/**
 * @brief	显示字符串
 * @param	x,y:起点坐标
 * @param	p:字符串起始地址
 * @note	用16字体
 */
void LCD_ShowString(uint16_t x, uint16_t y, const uint8_t *p);

#endif

/**
 * @file	oled.c
 * @brief	oled驱动C文件
 */
 
#include "oled.h"
#include "font.h"

uint16_t BACK_COLOR = BLACK; //Background
uint16_t POINT_COLOR = RED;  //Draw Piont

void LCD_Writ_Bus(char dat)	 //串行数据写入
{
   
	uint8_t i;

	for (i = 0; i < 8; i++)
	{
   
		OLED_SCLK_Clr();
		if (dat & 0x80)
			OLED_SDIN_Set();
		else
		OLED_SDIN_Clr();
		OLED_SCLK_Set();
		dat <<= 1;
	}
}

void LCD_WR_DATA8(char da) //发送数据-8位参数
{
   						   //OLED_CS_Clr();
	OLED_DC_Set();
	LCD_Writ_Bus(da);
//	OLED_CS_Set();
}
void LCD_WR_DATA(int da)
{
    
//    OLED_CS_Clr();
	OLED_DC_Set();
	LCD_Writ_Bus(da >> 8);
	LCD_Writ_Bus(da);
//	OLED_CS_Set();
}
void LCD_WR_REG(char da)
{
    
//    OLED_CS_Clr();
	OLED_DC_Clr();
	LCD_Writ_Bus(da);
//	OLED_CS_Set();
}
void LCD_WR_REG_DATA(int reg, int da)
{
    
//    OLED_CS_Clr();
	LCD_WR_REG(reg);
	LCD_WR_DATA(da);
//	OLED_CS_Set();
}

void Address_set(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
{
   
	LCD_WR_REG(0x2a);
	LCD_WR_DATA8(x1 >> 8);
	LCD_WR_DATA8(x1);
	LCD_WR_DATA8(x2 >> 8);
	LCD_WR_DATA8(x2);

	LCD_WR_REG(0x2b);
	LCD_WR_DATA8(y1 >> 8);
	LCD_WR_DATA8(y1);
	LCD_WR_DATA8(y2 >> 8);
	LCD_WR_DATA8(y2);

	LCD_WR_REG(0x2C);
}

void LCD_Init(void)
{
   
    pinMode(1, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(11, OUTPUT);

//	OLED_CS_Clr();  //打开片选使能
	OLED_RST_Clr();
	delay(200);
	OLED_RST_Set();
	delay(200);
	OLED_BLK_Set();

	//************* Start Initial Sequence **********//
	LCD_WR_REG(0x36);
	LCD_WR_DATA8(0x00);

	LCD_WR_REG(0x3A);
	LCD_WR_DATA8(0x05);

	LCD_WR_REG(0xB2);
	LCD_WR_DATA8(0x0C);
	LCD_WR_DATA8(0x0C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x33);
	LCD_WR_DATA8(0x33);

	LCD_WR_REG(0xB7);
	LCD_WR_DATA8(0x35);

	LCD_WR_REG(0xBB);
	LCD_WR_DATA8(0x19);

	LCD_WR_REG(0xC0);
	LCD_WR_DATA8(0x2C);

	LCD_WR_REG(0xC2);
	LCD_WR_DATA8(0x01);

	LCD_WR_REG(0xC3);
	LCD_WR_DATA8(0x12);

	LCD_WR_REG(0xC4);
	LCD_WR_DATA8(0x20);

	LCD_WR_REG(0xC6);
	LCD_WR_DATA8(0x0F);

	LCD_WR_REG(0xD0);
	LCD_WR_DATA8(0xA4);
	LCD_WR_DATA8(0xA1);

	LCD_WR_REG(0xE0);
	LCD_WR_DATA8(0xD0);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x0D);
	LCD_WR_DATA8(0x11);
	LCD_WR_DATA8(0x13);
	LCD_WR_DATA8(0x2B);
	LCD_WR_DATA8(0x3F);
	LCD_WR_DATA8(0x54);
	LCD_WR_DATA8(0x4C);
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x0D);
	LCD_WR_DATA8(0x0B);
	LCD_WR_DATA8(0x1F);
	LCD_WR_DATA8(0x23);

	LCD_WR_REG(0xE1);
	LCD_WR_DATA8(0xD0);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x0C);
	LCD_WR_DATA8(0x11);
	LCD_WR_DATA8(0x13);
	LCD_WR_DATA8(0x2C);
	LCD_WR_DATA8(0x3F);
	LCD_WR_DATA8(0x44
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值