好久没写关于netduino的文章了,工作忙是一方面,主要原因还是因为没解决TFT显示的问题,功夫不负有心人,在经过多轮研究后,总算在今天2013年12月15日的晚上9点解决了。
下面先介绍一下我所用的这款tft
OJ TFT液晶屏是含有插针和背光的LCD屏,使用TFT library 库文件,你可以显示文本、图片等。液晶背面含有板载的micro-SD卡槽,使您能够存储位图图像并在屏幕上显示。屏幕的引脚扩展接口完全兼容 Arduino Esplora 可以直接插在扩展口上。
模块尺寸:60mm*42mm
像素:128(RGB)*160
显示色彩:全彩
供电电压:5V
a.正面 | b.反面 | ||
引脚号 | 标识 | 功能 | |
1 | +5V | 电源DC 5V+ | |
2 | MISO | SPI接口 | |
3 | SCK | ||
4 | MOSI | ||
5 | CS-LD | 液晶屏使能 | |
6 | CS-TF | TF卡使能 | |
7 | D/C-LD | 液晶屏数据/指令控制 | |
8 | RESET | 液晶屏复位 | |
9 | BL | 液晶屏背光控制:
背光亮:置High,并可通过PWM控制亮度 背光灭:置Low或悬空 |
|
10 | GND | 电源DC地 |
TFT淘宝地址:
http://item.taobao.com/item.htm?spm=686.1000925.1000774.17.ttK7h5&id=35934491963
Netduino淘宝地址:
http://item.taobao.com/item.htm?spm=686.1000925.1000774.32.ttK7h5&id=21448079990
netduino与ST7735的接线
netduino D11 -----ST7735 MOSI
netduino D12 -----ST7735 MISO
netduino D13 -----ST7735 SCK
netduino D9 -----ST7735 CS-LD
netduino D7 -----ST7735 D/C-LD
netduino D8 -----ST7735 RESET
netduino D1 -----ST7735 BL
netduino 5v -----ST7735 5v
netduino GND -----ST7735 GND
通过与arduino的驱动对比,修改了从netduinohelper上下在的st7735驱动,对比了arduino和netduinohelper的驱动的区别, 修改对应的寄存器参数才可以正常显示
这款tft的优点是采用spi口,可以节省相关的D口接线。
SPI初始化
var extendedSpiConfig = new ExtendedSpiConfiguration(
SPI_mod: spiModule,
ChipSelect_Port: chipSelect,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: speedKHz,
BitsPerTransfer: 8);
Spi = new SPI(extendedSpiConfig);
初始化寄存器
private void Initialize()
{
Reset.Write(true);
Thread.Sleep(50);
Reset.Write(false);
Thread.Sleep(50);
Reset.Write(true);
Thread.Sleep(50);
DataCommand.Write(Command);
Write((byte)LcdCommand.SWRESET); // software reset
Thread.Sleep(150);
DataCommand.Write(Command);
Write((byte)LcdCommand.SLPOUT); // out of sleep mode
Thread.Sleep(255);
DataCommand.Write(Command);
Write((byte)LcdCommand.FRMCTR1); // frame rate control - normal mode
DataCommand.Write(Data);
Write(0x01); // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D)
Write(0x2C);
Write(0x2D);
DataCommand.Write(Command);
Write((byte)LcdCommand.FRMCTR2); // frame rate control - idle mode
DataCommand.Write(Data);
Write(0x01); // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D)
Write(0x2C);
Write(0x2D);
DataCommand.Write(Command);
Write((byte)LcdCommand.FRMCTR3); // frame rate control - partial mode
DataCommand.Write(Data);
Write(0x01); // dot inversion mode
Write(0x2C);
Write(0x2D);
Write(0x01); // line inversion mode
Write(0x2C);
Write(0x2D);
DataCommand.Write(Command);
Write((byte)LcdCommand.INVCTR); // display inversion control
DataCommand.Write(Data);
Write(0x07); // no inversion
DataCommand.Write(Command);
Write((byte)LcdCommand.PWCTR1); // power control
DataCommand.Write(Data);
Write(0xA2);
Write(0x02); // -4.6V
Write(0x84); // AUTO mode
DataCommand.Write(Command);
Write((byte)LcdCommand.PWCTR2); // power control
DataCommand.Write(Data);
Write(0xC5); // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
DataCommand.Write(Command);
Write((byte)LcdCommand.PWCTR3); // power control
DataCommand.Write(Data);
Write(0x0A); // Opamp current small
Write(0x00); // Boost frequency
DataCommand.Write(Command);
Write((byte)LcdCommand.PWCTR4); // power control
DataCommand.Write(Data);
Write(0x8A); // BCLK/2, Opamp current small & Medium low
Write(0x2A);
Write((byte)LcdCommand.PWCTR5); // power control
DataCommand.Write(Data);
Write(0x8A);
Write(0xEE);
DataCommand.Write(Command);
Write((byte)LcdCommand.VMCTR1); // power control
DataCommand.Write(Data);
Write(0x0E);
DataCommand.Write(Command);
Write((byte)LcdCommand.INVOFF); // don't invert display
DataCommand.Write(Command);
Write((byte)LcdCommand.MADCTL); // memory access control (directions)
DataCommand.Write(Data);
Write(0xC8); // row address/col address, bottom to top refresh
DataCommand.Write(Command);
Write((byte)LcdCommand.COLMOD); // set color mode
DataCommand.Write(Data);
Write(0x05); // 16-bit color
DataCommand.Write(Command);
Write((byte)LcdCommand.CASET); // column addr set
DataCommand.Write(Data);
Write(0x00);
Write(0x00); // XSTART = 0
Write(0x00);
Write(0x7F); // XEND = 127
DataCommand.Write(Command);
Write((byte)LcdCommand.RASET); // row addr set
DataCommand.Write(Data);
Write(0x00);
Write(0x00); // XSTART = 0
Write(0x00);
Write(0x9F); // XEND = 159
DataCommand.Write(Command);
Write((byte)LcdCommand.GMCTRP1);
DataCommand.Write(Data);
Write(0x02);
Write(0x1c);
Write(0x07);
Write(0x12);
Write(0x37);
Write(0x32);
Write(0x29);
Write(0x2d);
Write(0x29);
Write(0x25);
Write(0x2B);
Write(0x39);
Write(0x00);
Write(0x01);
Write(0x03);
Write(0x10);
DataCommand.Write(Command);
Write((byte)LcdCommand.GMCTRN1);
DataCommand.Write(Data);
Write(0x03);
Write(0x1d);
Write(0x07);
Write(0x06);
Write(0x2E);
Write(0x2C);
Write(0x29);
Write(0x2D);
Write(0x2E);
Write(0x2E);
Write(0x37);
Write(0x3F);
Write(0x00);
Write(0x00);
Write(0x02);
Write(0x10);
DataCommand.Write(Command);
Write((byte)LcdCommand.NORON); // normal display on
Thread.Sleep(10);
DataCommand.Write(Command);
Write((byte)LcdCommand.DISPON);
Thread.Sleep(100);
//SetAddressWindow(0, 0, (byte)(Width - 1), (byte)(Height - 1));
//SetAddressWindow(0, 0, Width - 1, Height - 1);
DataCommand.Write(Data);
}
初始化之后就可以调用相关的函数绘制图形了
附上驱动代码
ST7735TFT.cs
using System; using System.Threading; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; namespace ST7735TFT { /// <summary> /// netduino ST7735 driver (based on AdaFruit's library http://github.com/adafruit/ST7735-Library) /// </summary> public class ST7735TFT : IDisposable { public byte Width { get; set; } public byte Height { get; set; } public enum LcdCommand { NOP = 0x0, SWRESET = 0x01, RDDID = 0x04, RDDST = 0x09, SLPIN = 0x10, SLPOUT = 0x11, PTLON = 0x12, NORON = 0x13, INVOFF = 0x20, INVON = 0x21, DISPOFF = 0x28, DISPON = 0x29, CASET = 0x2A, RASET = 0x2B, RAMWR = 0x2C, RAMRD = 0x2E, PTLAR = 0x30, COLMOD = 0x3A, MADCTL = 0x36, FRMCTR1 = 0xB1, FRMCTR2 = 0xB2, FRMCTR3 = 0xB3, INVCTR = 0xB4, DISSET5 = 0xB6, PWCTR1 = 0xC0, PWCTR2 = 0xC1, PWCTR3 = 0xC2, PWCTR4 = 0xC3, PWCTR5 = 0xC4, VMCTR1 = 0xC5, RDID1 = 0xDA, RDID2 = 0xDB, RDID3 = 0xDC, RDID4 = 0xDD, PWCTR6 = 0xFC, GMCTRP1 = 0xE0, GMCTRN1 = 0xE1 } public enum Colors { Black = 0x0000, Blue = 0x001F, Red = 0xF800, Green = 0x07E0, Cyan = 0x07FF, Magenta = 0xF81F, Yellow = 0xFFE0, White = 0xFFFF } public ST7735TFT( Cpu.Pin chipSelect, Cpu.Pin dc, Cpu.Pin reset, SPI.SPI_module spiModule = SPI.SPI_module.SPI1, uint speedKHz = (uint)9500, VirtualMemory vm = null) { Width = 128; Height = 160; AutoRefreshScreen = true; DataCommand = new OutputPort(dc, false); Reset = new OutputPort(reset, true); //SPI.Configuration SPI_Config = new SPI.Configuration(chipSelect, false, 0, 0, false, true, 10000, SPI.SPI_module.SPI1); var extendedSpiConfig = new ExtendedSpiConfiguration( SPI_mod: spiModule, ChipSelect_Port: chipSelect, ChipSelect_ActiveState: false, ChipSelect_SetupTime: 0, ChipSelect_HoldTime: 0, Clock_IdleState: false, Clock_Edge: true, Clock_RateKHz: speedKHz, BitsPerTransfer: 8); Spi = new SPI(extendedSpiConfig); if (vm == null) { SpiBuffer = new byte[Width * Height * sizeof(ushort)]; MemoryWriteFunction = SpiBufferWrite; } else { VM = vm; MemoryWriteFunction = VirtualMemoryWrite; } Initialize(); } public bool AutoRefreshScreen { get; set; } public void Refresh() { if (VM == null) { Spi.Write(SpiBuffer); } else { var address = 0; var memorySegments = (VM.Stream.Length / VM.Buffer.Length); var heightIncrement = Height / memorySegments; for (var y0 = 0; y0 < Height; y0 += (byte)heightIncrement) { SetAddressWindow(0, (byte)y0, (byte)(Width - 1), (byte)((y0 + heightIncrement) - 1)); VM.ReadVM(address, 0); address += VM.Buffer.Length; Spi.Write(VM.Buffer); } } } public ushort GetRGBColor(byte red, byte green, byte blue) { red &= 0x1F; ushort color = red; color <<= 6; green &= 0x3F; color |= green; color <<= 5; blue &= 0x1F; color |= blue; return color; } public void DrawPixel(int x, int y, ushort color) { SetPixel(x, y, color); if (AutoRefreshScreen) { Refresh(); } } // Bresenham's algorithm: http://en.wikipedia.org/wiki/Bresenham's_line_algorithm public void DrawLine(int startX, int startY, int endX, int endY, ushort color) { int steep = (System.Math.Abs(endY - startY) > System.Math.Abs(endX - startX)) ? 1 : 0; if (steep != 0) { Swap(ref startX, ref startY); Swap(ref endX, ref endY); } if (startX > endX) { Swap(ref startX, ref endX); Swap(ref startY, ref endY); } int dx, dy; dx = endX - startX; dy = System.Math.Abs(endY - startY); int err = dx / 2; int ystep = 0; if (startY < endY) { ystep = 1; } else { ystep = -1; } for (; startX < endX; startX++) { if (steep != 0) { SetPixel(startY, startX, color); } else { SetPixel(startX, startY, color); } err -= dy; if (err < 0) { startY += ystep; err += dx; } } if (AutoRefreshScreen) { Refresh(); } } public void DrawCircle(int centerX, int centerY, int radius, ushort color) { int f = 1 - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x = 0; int y = radius; SetPixel(centerX, centerY + radius, color); SetPixel(centerX, centerY - radius, color); SetPixel(centerX + radius, centerY, color); SetPixel(centerX - radius, centerY, color); while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; SetPixel(centerX + x, centerY + y, color); SetPixel(centerX - x, centerY + y, color); SetPixel(centerX + x, centerY - y, color); SetPixel(centerX - x, centerY - y, color); SetPixel(centerX + y, centerY + x, color); SetPixel(centerX - y, centerY + x, color); SetPixel(centerX + y, centerY - x, color); SetPixel(centerX - y, centerY - x, color); } if (AutoRefreshScreen) { Refresh(); } } public void ClearScreen(ushort color = (ushort) Colors.Black) { var high = (byte)(color >> 8); var low = (byte)color; var index = 0; if (VM == null) { SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; SpiBuffer[index++] = high; SpiBuffer[index++] = low; Array.Copy(SpiBuffer, 0, SpiBuffer, 16, 16); Array.Copy(SpiBuffer, 0, SpiBuffer, 32, 32); Array.Copy(SpiBuffer, 0, SpiBuffer, 64, 64); Array.Copy(SpiBuffer, 0, SpiBuffer, 128, 128); Array.Copy(SpiBuffer, 0, SpiBuffer, 256, 256); index = 512; var line = 0; var Half = Height / 2; while (++line < Half - 1) { Array.Copy(SpiBuffer, 0, SpiBuffer, index, 256); index += 256; } Array.Copy(SpiBuffer, 0, SpiBuffer, index, SpiBuffer.Length / 2); } else { for (; index < VM.Buffer.Length; ) { VM.Buffer[index++] = high; VM.Buffer[index++] = low; } VM.FillFromBuffer(); } if (AutoRefreshScreen) { Refresh(); } } public void Dispose() { Spi.Dispose(); SpiBuffer = null; Spi = null; DataCommand = null; Reset = null; VM = null; } private void Initialize() { Reset.Write(true); Thread.Sleep(50); Reset.Write(false); Thread.Sleep(50); Reset.Write(true); Thread.Sleep(50); DataCommand.Write(Command); Write((byte)LcdCommand.SWRESET); // software reset Thread.Sleep(150); DataCommand.Write(Command); Write((byte)LcdCommand.SLPOUT); // out of sleep mode Thread.Sleep(255); DataCommand.Write(Command); Write((byte)LcdCommand.FRMCTR1); // frame rate control - normal mode DataCommand.Write(Data); Write(0x01); // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) Write(0x2C); Write(0x2D); DataCommand.Write(Command); Write((byte)LcdCommand.FRMCTR2); // frame rate control - idle mode DataCommand.Write(Data); Write(0x01); // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) Write(0x2C); Write(0x2D); DataCommand.Write(Command); Write((byte)LcdCommand.FRMCTR3); // frame rate control - partial mode DataCommand.Write(Data); Write(0x01); // dot inversion mode Write(0x2C); Write(0x2D); Write(0x01); // line inversion mode Write(0x2C); Write(0x2D); DataCommand.Write(Command); Write((byte)LcdCommand.INVCTR); // display inversion control DataCommand.Write(Data); Write(0x07); // no inversion DataCommand.Write(Command); Write((byte)LcdCommand.PWCTR1); // power control DataCommand.Write(Data); Write(0xA2); Write(0x02); // -4.6V Write(0x84); // AUTO mode DataCommand.Write(Command); Write((byte)LcdCommand.PWCTR2); // power control DataCommand.Write(Data); Write(0xC5); // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD DataCommand.Write(Command); Write((byte)LcdCommand.PWCTR3); // power control DataCommand.Write(Data); Write(0x0A); // Opamp current small Write(0x00); // Boost frequency DataCommand.Write(Command); Write((byte)LcdCommand.PWCTR4); // power control DataCommand.Write(Data); Write(0x8A); // BCLK/2, Opamp current small & Medium low Write(0x2A); Write((byte)LcdCommand.PWCTR5); // power control DataCommand.Write(Data); Write(0x8A); Write(0xEE); DataCommand.Write(Command); Write((byte)LcdCommand.VMCTR1); // power control DataCommand.Write(Data); Write(0x0E); DataCommand.Write(Command); Write((byte)LcdCommand.INVOFF); // don't invert display DataCommand.Write(Command); Write((byte)LcdCommand.MADCTL); // memory access control (directions) DataCommand.Write(Data); Write(0xC8); // row address/col address, bottom to top refresh DataCommand.Write(Command); Write((byte)LcdCommand.COLMOD); // set color mode DataCommand.Write(Data); Write(0x05); // 16-bit color DataCommand.Write(Command); Write((byte)LcdCommand.CASET); // column addr set DataCommand.Write(Data); Write(0x00); Write(0x00); // XSTART = 0 Write(0x00); Write(0x7F); // XEND = 127 DataCommand.Write(Command); Write((byte)LcdCommand.RASET); // row addr set DataCommand.Write(Data); Write(0x00); Write(0x00); // XSTART = 0 Write(0x00); Write(0x9F); // XEND = 159 DataCommand.Write(Command); Write((byte)LcdCommand.GMCTRP1); DataCommand.Write(Data); Write(0x02); Write(0x1c); Write(0x07); Write(0x12); Write(0x37); Write(0x32); Write(0x29); Write(0x2d); Write(0x29); Write(0x25); Write(0x2B); Write(0x39); Write(0x00); Write(0x01); Write(0x03); Write(0x10); DataCommand.Write(Command); Write((byte)LcdCommand.GMCTRN1); DataCommand.Write(Data); Write(0x03); Write(0x1d); Write(0x07); Write(0x06); Write(0x2E); Write(0x2C); Write(0x29); Write(0x2D); Write(0x2E); Write(0x2E); Write(0x37); Write(0x3F); Write(0x00); Write(0x00); Write(0x02); Write(0x10); DataCommand.Write(Command); Write((byte)LcdCommand.NORON); // normal display on Thread.Sleep(10); DataCommand.Write(Command); Write((byte)LcdCommand.DISPON); Thread.Sleep(100); //SetAddressWindow(0, 0, (byte)(Width - 1), (byte)(Height - 1)); //SetAddressWindow(0, 0, Width - 1, Height - 1); DataCommand.Write(Data); } private ScreenOrientation _orientation = ScreenOrientation.Portrait; public ScreenOrientation Orientation { get { return _orientation; } set { _orientation = value; DataCommand.Write(Command); Write((byte)LcdCommand.MADCTL); DataCommand.Write(Data); Write((byte)_orientation); if (_orientation == ScreenOrientation.Portrait) { Width = 128; Height = 160; } else { Width = 160; Height = 128; } SetAddressWindow(0, 0, (byte)(Width - 1), (byte)(Height - 1)); } } private void SetAddressWindow(byte x0, byte y0, byte x1, byte y1) { DataCommand.Write(Command); Write((byte)LcdCommand.CASET); // column addr set DataCommand.Write(Data); Write(0x00); Write((byte)(x0 + 1)); // XSTART Write(0x00); Write((byte)(x1 + 1)); // XEND DataCommand.Write(Command); Write((byte)LcdCommand.RASET); // row addr set DataCommand.Write(Data); Write(0x00); Write((byte)(y0 + 2)); // YSTART Write(0x00); Write((byte)(y1 + 2)); // YEND DataCommand.Write(Command); Write((byte)LcdCommand.RAMWR); // write to RAM DataCommand.Write(Data); } private void SetPixel(int x, int y, ushort color) { if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height)) return; var index = ((y * Width) + x) * sizeof(ushort); MemoryWriteFunction(index, (byte)(color >> 8)); MemoryWriteFunction(++index, (byte)(color)); //if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height)) return; //var index = ((y * Width) + x) * sizeof(ushort); //SpiBuffer[index] = (byte)(color >> 8); //SpiBuffer[++index] = (byte)(color); } private const bool Data = true; private const bool Command = false; protected void Write(byte Byte) { SpiBOneByteBuffer[0] = Byte; Spi.Write(SpiBOneByteBuffer); } private void Swap(ref int a, ref int b) { var t = a; a = b; b = t; } protected void VirtualMemoryWrite(long address, byte data) { VM.WriteVM(address, data); } protected void SpiBufferWrite(long address, byte data) { SpiBuffer[address] = data; } public byte[] SpiBuffer; public VirtualMemory VM; protected readonly byte[] SpiBOneByteBuffer = new byte[1]; protected OutputPort DataCommand; protected OutputPort Reset; protected SPI Spi; protected MemoryWrite MemoryWriteFunction; protected delegate void MemoryWrite(long address, byte data); } public enum ScreenOrientation { Portrait = 0xC8, Landscape = 0x68 } }
VirtualMemory.cs
用于将数据汇聚到虚拟内存中,统一写入
using System; using System.IO; using Microsoft.SPOT; namespace ST7735TFT { public class VirtualMemory : IDisposable { public byte[] Buffer; public FileStream Stream; public bool IsReadOnly { get; set; } public VirtualMemory(long capacityInBytes, int segments, string path) { IsReadOnly = false; if (segments <= 0) throw new ArgumentOutOfRangeException("bufferSize"); Buffer = new byte[capacityInBytes / segments]; Stream = new FileStream(path, FileMode.OpenOrCreate); if (Stream.Length == 0) { Stream.SetLength(capacityInBytes); } } public void WriteVM(long address, byte data, SeekOrigin origin = SeekOrigin.Begin) { if (IsReadOnly) throw new InvalidOperationException("readonly"); if (address > Stream.Length) throw new ArgumentOutOfRangeException("address"); Stream.Seek(address, origin); Stream.WriteByte(data); } public void WriteVM(long address, byte[] data, int byteCount = 0, SeekOrigin origin = SeekOrigin.Begin) { if (IsReadOnly) throw new InvalidOperationException("readonly"); Stream.Seek(address, origin); if (byteCount == 0) { if (address + data.Length > Stream.Length) throw new ArgumentOutOfRangeException("address"); Stream.Write(data, 0, data.Length); } else { if (address + byteCount > Stream.Length) throw new ArgumentOutOfRangeException("address"); Stream.Write(data, 0, byteCount); } } public byte ReadVM(long address, SeekOrigin origin = SeekOrigin.Begin) { Stream.Seek(address, origin); return (byte)Stream.ReadByte(); } public int ReadVM(long address, int offsetInbuffer, int readBytecount = 0, SeekOrigin origin = SeekOrigin.Begin) { Stream.Seek(address, origin); if (readBytecount == 0) { return Stream.Read(Buffer, 0, Buffer.Length); } else { if (readBytecount > Buffer.Length) throw new ArgumentOutOfRangeException("readBytecount"); return Stream.Read(Buffer, offsetInbuffer, readBytecount); } } public void FillFromBuffer() { if (IsReadOnly) throw new InvalidOperationException("readonly"); var address = 0; while (address < Stream.Length) { WriteVM(address, Buffer); address += Buffer.Length; } } public void ConnectExistingStream(string path, bool readOnly = true) { Stream.Dispose(); Stream = null; Debug.GC(true); Stream = new FileStream(path, FileMode.Open); IsReadOnly = readOnly; } public void RedefineBufferSize(int bufferSize) { Buffer = null; Debug.GC(true); Buffer = new byte[bufferSize]; } public virtual void Copy(VirtualMemory source) { if (IsReadOnly) throw new InvalidOperationException("readonly"); var address = 0; Stream.SetLength(source.Stream.Length); while (address < source.Stream.Length) { var sourceBytesRead = source.ReadVM(address, 0); WriteVM(address, source.Buffer, sourceBytesRead); address += sourceBytesRead; } } public void Dispose() { Buffer = null; Stream.Close(); Stream.Dispose(); Stream = null; Debug.GC(true); } } }
Program.cs
背光板接到GPIO_PIN_D1,初始需要设置为true,这样表示显示背光,为啥这样这是我调试的经验,原因未知
static OutputPort p1 = new OutputPort(Pins.GPIO_PIN_D1, true);
文件里的代码如下:
#define NETDUINO using System; using System.IO; using System.Threading; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.IO; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; namespace ST7735TFT { public class Program { //public static ST7735TFT tft = new ST7735TFT(Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D7, Pins.GPIO_PIN_D8, speedKHz: 40000); static OutputPort p1 = new OutputPort(Pins.GPIO_PIN_D1, true); public static ST7735TFT tft = new ST7735TFT(Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D7, Pins.GPIO_PIN_D8, speedKHz: 40000); public static void Main() { //DisplayPicture(); //tft.AutoRefreshScreen = true; //p1.Write(false); while (true) { tft.ClearScreen(); //DisplayGradient(); tft.DrawCircle(70, 70, 30, (ushort)ST7735TFT.Colors.Red); Thread.Sleep(500); //DisplayCircles(); //DisplayColorFlow(); //tft.ClearScreen(); //DisplayLines(); } } public static void DisplayColorFlow() { #if NETDUINO_MINI StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_13); #else StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_D10); #endif while (true) { ReadPicture(@"SD\Pictures\ColorFlow1.bmp.24.bin", 0); ReadPicture(@"SD\Pictures\ColorFlow2.bmp.24.bin", 0); ReadPicture(@"SD\Pictures\ColorFlow3.bmp.24.bin", 0); ReadPicture(@"SD\Pictures\ColorFlow4.bmp.24.bin", 0); } } public static void DisplayPicture() { #if NETDUINO_MINI StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_13); #else StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_D10); #endif ReadPicture(@"SD\Pictures\spaceneedle.bmp.24.bin"); ReadPicture(@"SD\Pictures\spaceneedleclose.bmp.24.bin"); ReadPicture(@"SD\Pictures\spaceneedlesunset.bmp.24.bin"); ReadPicture(@"SD\Pictures\spaceneedleatnight.bmp.24.bin"); StorageDevice.Unmount("SD"); } public static void ReadPicture(string filename, int delay = 1000) { using (var filestream = new FileStream(filename, FileMode.Open)) { filestream.Read(tft.SpiBuffer, 0, tft.SpiBuffer.Length); tft.Refresh(); Thread.Sleep(delay); } } public static void DisplayLines() { byte red = 20; byte green = 1; byte blue = 5; var y = 0; for (; y < tft.Height; y++) { red += 2; green++; tft.DrawLine(0, 0, tft.Width, y, tft.GetRGBColor(red, green, blue)); tft.Refresh(); } red = 20; green = 1; blue = 5; for (; y >= 0; y--) { red += 2; green++; tft.DrawLine(tft.Width - 1, tft.Height - 1, 0, y, tft.GetRGBColor(red, green, blue)); tft.Refresh(); } } public static void DisplayCircles() { var xHalf = tft.Width / 2; var yHalf = tft.Height / 2; byte red = 1; byte green = 1; byte blue = 1; for (var r = 1; r < xHalf; r += 2) { var color = tft.GetRGBColor(red, green, blue); tft.DrawCircle(xHalf, yHalf, r, color); red += 3; green += 2; blue += 1; tft.Refresh(); } Thread.Sleep(1000); for (var I = 0; I < 2; I++) { var r = 1; for (; r < xHalf; r += 2) { tft.DrawCircle(xHalf, yHalf, r, (ushort)ST7735TFT.Colors.White); tft.Refresh(); tft.DrawCircle(xHalf, yHalf, r, (ushort)ST7735TFT.Colors.Black); } for (; r > 1; r -= 2) { tft.DrawCircle(xHalf, yHalf, r, (ushort)ST7735TFT.Colors.White); tft.Refresh(); tft.DrawCircle(xHalf, yHalf, r, (ushort)ST7735TFT.Colors.Black); } } Thread.Sleep(1000); } public static void DisplayGradient() { var x = 0; var y = 0; while (y < tft.Height) { byte red = 1; for (; red < 32; red += 3) { byte green = 1; for (; green < 33; green += 2) { byte blue = 1; for (; blue < 32; blue += 2) { var color = tft.GetRGBColor(red, green, blue); tft.DrawPixel(x++, y, color); if (x >= tft.Width) { x = 0; y++; } } } } tft.Refresh(); } } public static void draw() { tft.DrawLine(0, 0,22, 50, tft.GetRGBColor(1, 255, 36)); tft.Refresh(); } } }