首先先須先熟悉如何使用Raspberry Pi的GPIO腳位,並確認映射關係
圖片引用自:http://blog.mcmelectronics.com/post/Raspberry-Pi-3-GPIO-Pin-Layout#.WDAR9HE2u00
接著開始編寫操作GPIO的主要函式,這裡的程式是改寫自
elinux.org/RPi_GPIO_Code_Samples,其主要功能為,初始化GPIO、設定選定的GPIO腳位為
輸出或輸入、若是該腳位為輸出時,則可設定輸出為1或是0。需要注意的是你使用的
Raspberry Pi不是3 model B的話,可能需要更改GPIO_BASE。
程式碼如下:
gpio.h
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #define GPIO_BASE 0x3f200000 #define PAGE_SIZE (4 * 1024) #define BLOCK_SIZE (4 * 1024) int mem_fd; void *gpio_map; /* I/O access */ volatile unsigned *gpio; /* GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) */ #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) #define GPIO_SET *(gpio+7) /* sets bits which are 1 ignores bits which are 0 */ #define GPIO_CLR *(gpio+10) /* clears bits which are 1 ignores bits which are 0 */ /** * Set up a memory regions to access GPIO * */ void ini_gpio(); void set_gpio(int num,int in_out);//0 for in, 1 for out void gpio_val(int num,int val);gpio.c
#include "gpio.h" void ini_gpio() { /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem \n"); exit(-1); } /* mmap GPIO */ gpio_map = mmap( NULL, /* Any adddress in our space will do */ BLOCK_SIZE, /* Map length */ PROT_READ|PROT_WRITE, /* Enable reading & writting to mapped memory */ MAP_SHARED, /* Shared with other processes */ mem_fd, /* File to map */ GPIO_BASE /* Offset to GPIO peripheral */ ); close(mem_fd); /* No need to keep mem_fd open after mmap */ if (gpio_map == MAP_FAILED) { printf("mmap error %d\n", (int)gpio_map); /* errno also set! */ exit(-1); } /* Always use volatile pointer! */ gpio = (volatile unsigned *)gpio_map; } void set_gpio(int num,int in_out)//0 for in, 1 for out { INP_GPIO(num); if(in_out==1) { OUT_GPIO(num); } return; } void gpio_val(int num,int val) { if(val==1) { GPIO_SET = 1 << num; } else { GPIO_CLR = 1 << num; } return; }寫完GPIO的函式後,可以先寫簡單的程式測試是否可以使用,如此範例為將led燈接上GPIO腳位的編號4:
#include "gpio.h" #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include "gpio.h" int main(int argc, char **argv) { /* Set up gpi pointer for direct register access */ ini_gpio(); set_gpio(4,1); gpio_val(4,1); sleep(1); gpio_val(4,0); sleep(1); return 0; }開始編寫驅動tft螢幕的程式,參考http://forum.arduino.cc/index.php?topic=125034.0裡二樓 Arduino版本的實作st7735r的code並改寫。這裡需要注意的地方是reset, cs, scl, sda, rs對應到的GPIO標號,在這裡分別設定為GPIO編號2, 3, 4, 5, 6, 與GPIO編號對應到Raspberry Pi板子上的腳位,和Raspberry Pi的腳位對應到st7735r的腳位。 st7735r.h:
#include "gpio.h" extern unsigned char reset; extern unsigned char cs; extern unsigned char scl; extern unsigned char sda; extern unsigned char rs; int bitSet(unsigned char num,int pos); void write_command(unsigned char c); void write_data(unsigned char d); void write_data_2(unsigned char LCD_DataH,unsigned char LCD_DataL); void write_data_3(unsigned char LCD_DataH,unsigned char LCD_DataM,unsigned char LCD_DataL); void Reset(); void lcd_initial(); void RamAdressSet(); void dsp_single_colour(unsigned char DH,unsigned char DL); void PutPixel(unsigned int x_start,unsigned int y_start,unsigned int color);st7735r.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <math.h> #include "st7735r.h" unsigned char reset=2; unsigned char cs=3; unsigned char scl=4; unsigned char sda=5; unsigned char rs=6; int bitSet(unsigned char num,int pos) { if((num & (int)(pow(2,pos)))>0) { return 1; } return 0; } void write_command(unsigned char c){ gpio_val(cs,0); gpio_val(rs,0); gpio_val(sda,bitSet(c,7)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,6)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,5)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,4)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,3)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,2)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,1)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(c,0)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(cs,1); } void write_data(unsigned char d) { gpio_val(cs,0); gpio_val(rs,1); gpio_val(sda,bitSet(d,7)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,6)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,5)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,4)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,3)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,2)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,1)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(sda,bitSet(d,0)); gpio_val(scl,0); gpio_val(scl,1); gpio_val(cs,1); } void write_data_2(unsigned char LCD_DataH,unsigned char LCD_DataL) { write_data(LCD_DataH); write_data(LCD_DataL); } void write_data_3(unsigned char LCD_DataH,unsigned char LCD_DataM,unsigned char LCD_DataL) { write_data(LCD_DataH); write_data(LCD_DataM); write_data(LCD_DataL); } void Reset() { gpio_val(reset,0); usleep(100000); gpio_val(reset,1); usleep(100000); } ////////////////////////////////////////////////////////////////////////////////////////////// void lcd_initial(){ ini_gpio(); set_gpio(reset,1); set_gpio(cs,1); set_gpio(scl,1); set_gpio(sda,1); set_gpio(rs,1); printf("start reset\n"); Reset(); printf("start soft reset\n"); //------------------------------------------------------------------// //-------------------Software Reset-------------------------------// //------------------------------------------------------------------// write_command(0x11);//Sleep exit usleep(120000); //ST7735R Frame Rate write_command(0xB1); write_data(0x01); write_data(0x2C); write_data(0x2D); write_command(0xB2); write_data(0x01); write_data(0x2C); write_data(0x2D); write_command(0xB3); write_data(0x01); write_data(0x2C); write_data(0x2D); write_data(0x01); write_data(0x2C); write_data(0x2D); write_command(0xB4); //Column inversion write_data(0x07); //ST7735R Power Sequence write_command(0xC0); write_data(0xA2); write_data(0x02); write_data(0x84); write_command(0xC1); write_data(0xC5); write_command(0xC2); write_data(0x0A); write_data(0x00); write_command(0xC3); write_data(0x8A); write_data(0x2A); write_command(0xC4); write_data(0x8A); write_data(0xEE); write_command(0xC5); //VCOM write_data(0x0E); write_command(0x36); //MX, MY, RGB mode write_data(0xC8); //ST7735R Gamma Sequence write_command(0xe0); write_data(0x0f); write_data(0x1a); write_data(0x0f); write_data(0x18); write_data(0x2f); write_data(0x28); write_data(0x20); write_data(0x22); write_data(0x1f); write_data(0x1b); write_data(0x23); write_data(0x37); write_data(0x00); write_data(0x07); write_data(0x02); write_data(0x10); write_command(0xe1); write_data(0x0f); write_data(0x1b); write_data(0x0f); write_data(0x17); write_data(0x33); write_data(0x2c); write_data(0x29); write_data(0x2e); write_data(0x30); write_data(0x30); write_data(0x39); write_data(0x3f); write_data(0x00); write_data(0x07); write_data(0x03); write_data(0x10); write_command(0x2a); write_data(0x00); write_data(0x00); write_data(0x00); write_data(0x7f); write_command(0x2b); write_data(0x00); write_data(0x00); write_data(0x00); write_data(0x9f); write_command(0xF0); //Enable test command write_data(0x01); write_command(0xF6); //Disable ram power save mode write_data(0x00); write_command(0x3A); //65k mode write_data(0x05); write_command(0x29);//Display on } void RamAdressSet(){ write_command(0x2A); write_data(0x00); write_data(0x00); write_data(0x00); write_data(0x7f); write_command(0x2B); write_data(0x00); write_data(0x00); write_data(0x00); write_data(0x9f); } void dsp_single_colour(unsigned char DH,unsigned char DL) { unsigned char i,j; //RamAdressSet(); for (i=0;i<160;i++){ for (j=0;j<128;j++){ write_data_2(DH,DL); } } } void PutPixel(unsigned int x_start,unsigned int y_start,unsigned int color) { write_command(0x2a); write_data(x_start); write_data(0x5f); write_command(0x2b); write_data(y_start+0x34); write_data(0x7F); write_command(0x2c); write_data(color>>8); write_data(color&0xff); }test_tft.c:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "st7735r.h" int main() { printf("%d\n",bitSet(10,4)); printf("%d\n",bitSet(10,3)); lcd_initial(); while(1) { static unsigned char i = 0; i += 10; usleep(100000); printf("write command\n"); write_command(0x2C); dsp_single_colour(i,i); } return 0; }