TA的每日心情 | 奋斗 2015-10-5 14:38 |
---|
签到天数: 175 天 连续签到: 1 天 [LV.7]常住居民III
|
今天用硬件SPI刷了个屏幕显示。很是激动。主控使用SAM4L Xplained Pro starter kit套件实现。是基于Atmel官方的固件库实现的,自己建的模板,这样方便源代码共享到网上。主要用到这几个函数:
外设复用函数:
ioport_set_pin_mode(xxx, xxx);
ioport_disable_pin(xxx);
端口模式设置函数:
ioport_set_pin_dir(xxx, xxx);
ioport_set_pin_mode(xxx, xxx);
电平状态设置函数:
arch_ioport_set_pin_level(xxx,x )
现在我来简单说说这几个函数的用途和用法吧:
1.ioport_set_pin_mode(xxx, xxx); 这个函数是管脚功能选择函数:
例如:把PORTC30脚设为SPI的SCK时钟脚,可以这样写:
ioport_set_pin_mode(PIN_PC30B_SPI_SCK, MUX_PC30B_SPI_SCK);
2.ioport_disable_pin(xxx);这个函数是复用功能使能函数,记住一定加上这句话,这样复用功能的外设才能工作。例如把PORTC30脚设为SPI的SCK时钟脚功能打开,可以这样写:
ioport_disable_pin(PIN_PC30B_SPI_SCK);
3.ioport_set_pin_dir(xxx, xxx);这个函数是管脚的方向设置函数,例如把PORTC08脚设为输出可以这样写:
ioport_set_pin_dir(PIN_PC08, IOPORT_DIR_OUTPUT);
4.arch_ioport_set_pin_level(xxx,x ):最后是管脚电平状态设置函数,这个函数带两个参数输入的,例如把PORTC08的管脚设为低电平,写法如下:
arch_ioport_set_pin_level(PIN_PC08, 0 );
现在我来说说我函数的流程吧:
函数首先是进行sysclk_init()函数打开所有GPIO的时钟操作,这个跟STM32的芯片一个样的,要用到某些外设时,要打开相应的外设的时钟。
然后是设置串口,初始化TFT屏幕,然后用串口向电脑打印信息,最后就是一直刷新屏幕,显示21ic的图标和我论坛的ID号:
主函数的代码如下:
int main(){ sysclk_init(); arch_ioport_init(); ioport_set_pin_dir(PIN_PC07, IOPORT_DIR_OUTPUT); ioport_set_pin_level(PIN_PC07, IOPORT_PIN_LEVEL_LOW); ioport_set_pin_mode(PIN_PC26A_USART1_RXD, MUX_PC26A_USART1_RXD); ioport_disable_pin(PIN_PC26A_USART1_RXD); ioport_set_pin_mode(PIN_PC27A_USART1_TXD, MUX_PC27A_USART1_TXD); ioport_disable_pin(PIN_PC27A_USART1_TXD); /* //配置板子上的硬件SPI ioport_set_pin_mode(PIN_PA21A_SPI_MISO, MUX_PA21A_SPI_MISO);//把PORTA21配置成MSIO ioport_disable_pin(PIN_PA21A_SPI_MISO); //使能MSIO功能 ioport_set_pin_mode(PIN_PA22A_SPI_MOSI, MUX_PA22A_SPI_MOSI);//把PORTA22配置成MOSI ioport_disable_pin(PIN_PA22A_SPI_MOSI); //使能MOSI功能 ioport_set_pin_mode(PIN_PC30B_SPI_SCK, MUX_PC30B_SPI_SCK); //把PORTB30配置成SCK ioport_disable_pin(PIN_PC30B_SPI_SCK); //使能SCK功能 ioport_set_pin_mode(PIN_PB11B_SPI_NPCS2,MUX_PB11B_SPI_NPCS2);//把PORTB11配置成CS ioport_disable_pin(PIN_PB11B_SPI_NPCS2); //使能CS功能 ioport_set_pin_dir(UG_2832HSWEG04_DATA_CMD_GPIO, IOPORT_DIR_OUTPUT); ioport_set_pin_mode(UG_2832HSWEG04_DATA_CMD_GPIO, IOPORT_MODE_PULLUP); ioport_set_pin_dir(UG_2832HSWEG04_RESET_GPIO, IOPORT_DIR_OUTPUT); ioport_set_pin_mode(UG_2832HSWEG04_RESET_GPIO, IOPORT_MODE_PULLUP); configure_console(); //配置串口 ssd1306_init(); //初始化OLED ssd1306_clear(); //清OLED ssd1306_set_page_address(0); //行地址 ssd1306_set_column_address(0); //列地址 ssd1306_write_text("My ID is : qianzgai00001 !");//要显示的内容 ssd1306_set_page_address(2); ssd1306_set_column_address(30); ssd1306_write_text("----Thanks EEWORD !"); */ configure_console(); //配置串口 Lcd_Init(); printf("\r\n\r\n-- TFT试验 --\r\n"); printf("\r\n\r\n-- 强仔00001 --\r\n"); printf("\r\n\r\n-- 联系方式:963775289 --\r\n"); while (1) { //usart_getchar(USART1,&data); //usart_putchar(USART1,data); showimage(gImage_eeborad); } }SPI的底层函数:
#include "asf.h"//#define LCD_CTRL GPIOB //定义TFT数据端口为PB组//#define LCD_LED GPIO_Pin_9 //MCU_PB9 对应接液晶屏(或者模块)TFT --PIN_LED背光正极(背光可以由IO口提供电流,或者外接3.3V电压)#define LCD_RS_SET arch_ioport_set_pin_level(PIN_PC08, 1 )#define LCD_RS_CLR arch_ioport_set_pin_level(PIN_PC08, 0 )#define LCD_RST_SET arch_ioport_set_pin_level(PIN_PC09, 1 )#define LCD_RST_CLR arch_ioport_set_pin_level(PIN_PC09, 0 )#define LCD_SCL_SET arch_ioport_set_pin_level(PIN_PC30, 1 )#define LCD_SCL_CLR arch_ioport_set_pin_level(PIN_PC30, 0 )#define LCD_SDA_SET arch_ioport_set_pin_level(PIN_PA22, 1 )#define LCD_SDA_CLR arch_ioport_set_pin_level(PIN_PA22, 0 )void SPI2_Init(){ spi_flags_t spi_flags = SPI_MODE_0; board_spi_select_id_t spi_select_id = 0; //配置板子上的硬件SPI //ioport_set_pin_mode(PIN_PA21A_SPI_MISO, MUX_PA21A_SPI_MISO);//把PORTA21配置成MSIO //ioport_disable_pin(PIN_PA21A_SPI_MISO); //使能MSIO功能 ioport_set_pin_mode(PIN_PA22A_SPI_MOSI, MUX_PA22A_SPI_MOSI);//把PORTA22配置成MOSI ioport_disable_pin(PIN_PA22A_SPI_MOSI); //使能MOSI功能 ioport_set_pin_mode(PIN_PC30B_SPI_SCK, MUX_PC30B_SPI_SCK); //把PORTB30配置成SCK ioport_disable_pin(PIN_PC30B_SPI_SCK); //使能SCK功能 //ioport_set_pin_mode(PIN_PB11B_SPI_NPCS2,MUX_PB11B_SPI_NPCS2);//把PORTB11配置成CS //ioport_disable_pin(PIN_PB11B_SPI_NPCS2); ioport_set_pin_dir(PIN_PC08, IOPORT_DIR_OUTPUT); ioport_set_pin_mode(PIN_PC08, IOPORT_MODE_PULLUP); ioport_set_pin_dir(PIN_PC09, IOPORT_DIR_OUTPUT); ioport_set_pin_mode(PIN_PC09, IOPORT_MODE_PULLUP); struct spi_device device = { .id = SSD1306_CS_PIN, }; spi_master_init(SPI); spi_master_setup_device(SPI, &device, spi_flags,16000000, spi_select_id); spi_enable(SSD1306_SPI);}/**/u8 SPI_WriteByte(u8 Data){ struct spi_device device = {.id = SSD1306_CS_PIN}; spi_select_device(SSD1306_SPI, &device); spi_write_single(SPI,Data); spi_deselect_device(SSD1306_SPI, &device);}void Lcd_WriteIndex(u8 Index){ struct spi_device device = {.id = SSD1306_CS_PIN}; spi_select_device(SSD1306_SPI, &device); LCD_RS_CLR; spi_write_single(SPI, Index); spi_deselect_device(SSD1306_SPI, &device);}void Lcd_WriteData(u8 Data){ struct spi_device device = {.id = SSD1306_CS_PIN}; spi_select_device(SSD1306_SPI, &device); LCD_RS_SET; spi_write_single(SPI,Data); spi_deselect_device(SSD1306_SPI, &device);}/*u8 SPI_WriteByte1(u8 Data){ unsigned char i=0; for(i=8;i>0;i--) { if(Data&0x80) LCD_SDA_SET; //???? else LCD_SDA_CLR; LCD_SCL_CLR; LCD_SCL_SET; Data<<=1; }}void Lcd_WriteIndex1(u8 Index){ //SPI 写命令时序开始 //LCD_CS_CLR; LCD_RS_CLR; unsigned char i=0; for(i=8;i>0;i--) { if(Index&0x80) LCD_SDA_SET; //???? else LCD_SDA_CLR; LCD_SCL_CLR; LCD_SCL_SET; Index<<=1; }}void Lcd_WriteData1(u8 Data){ LCD_RS_SET; unsigned char i=0; for(i=8;i>0;i--) { if(Data&0x80) LCD_SDA_SET; //???? else LCD_SDA_CLR; LCD_SCL_CLR; LCD_SCL_SET; Data<<=1; }}*/void Lcd_WriteData16Bit(u8 DataH,u8 DataL){ Lcd_WriteData(DataH); Lcd_WriteData(DataL);}void Lcd_WriteIndex16Bit(u8 DataH,u8 DataL){ Lcd_WriteIndex(DataH); Lcd_WriteIndex(DataL);}void Lcd_Reset(void){ LCD_RST_CLR; delay_ms(100); LCD_RST_SET; delay_ms(50);}void Lcd_Init(void){ SPI2_Init(); Lcd_Reset(); Lcd_WriteIndex(0xCB); Lcd_WriteData(0x39); Lcd_WriteData(0x2C); Lcd_WriteData(0x00); Lcd_WriteData(0x34); Lcd_WriteData(0x02); Lcd_WriteIndex(0xCF); Lcd_WriteData(0x00); Lcd_WriteData(0XC1); Lcd_WriteData(0X30); Lcd_WriteIndex(0xE8); Lcd_WriteData(0x85); Lcd_WriteData(0x00); Lcd_WriteData(0x78); Lcd_WriteIndex(0xEA); Lcd_WriteData(0x00); Lcd_WriteData(0x00); Lcd_WriteIndex(0xED); Lcd_WriteData(0x64); Lcd_WriteData(0x03); Lcd_WriteData(0X12); Lcd_WriteData(0X81); Lcd_WriteIndex(0xF7); Lcd_WriteData(0x20); Lcd_WriteIndex(0xC0); //Power control Lcd_WriteData(0x23); //VRH[5:0] Lcd_WriteIndex(0xC1); //Power control Lcd_WriteData(0x10); //SAP[2:0];BT[3:0] Lcd_WriteIndex(0xC5); //VCM control Lcd_WriteData(0x3e); //对比度调节 Lcd_WriteData(0x28); Lcd_WriteIndex(0xC7); //VCM control2 Lcd_WriteData(0x86); //-- Lcd_WriteIndex(0x36); // Memory Access Control #ifdef H_VIEW Lcd_WriteData(0xE8); //C8 //48 68竖屏//28 E8 横屏#else Lcd_WriteData(0x48); #endif Lcd_WriteIndex(0x3A); Lcd_WriteData(0x55); Lcd_WriteIndex(0xB1); Lcd_WriteData(0x00); Lcd_WriteData(0x18); Lcd_WriteIndex(0xB6); // Display Function Control Lcd_WriteData(0x08); Lcd_WriteData(0x82); Lcd_WriteData(0x27); Lcd_WriteIndex(0xF2); // 3Gamma Function Disable Lcd_WriteData(0x00); Lcd_WriteIndex(0x26); //Gamma curve selected Lcd_WriteData(0x01); Lcd_WriteIndex(0xE0); //Set Gamma Lcd_WriteData(0x0F); Lcd_WriteData(0x31); Lcd_WriteData(0x2B); Lcd_WriteData(0x0C); Lcd_WriteData(0x0E); Lcd_WriteData(0x08); Lcd_WriteData(0x4E); Lcd_WriteData(0xF1); Lcd_WriteData(0x37); Lcd_WriteData(0x07); Lcd_WriteData(0x10); Lcd_WriteData(0x03); Lcd_WriteData(0x0E); Lcd_WriteData(0x09); Lcd_WriteData(0x00); Lcd_WriteIndex(0XE1); //Set Gamma Lcd_WriteData(0x00); Lcd_WriteData(0x0E); Lcd_WriteData(0x14); Lcd_WriteData(0x03); Lcd_WriteData(0x11); Lcd_WriteData(0x07); Lcd_WriteData(0x31); Lcd_WriteData(0xC1); Lcd_WriteData(0x48); Lcd_WriteData(0x08); Lcd_WriteData(0x0F); Lcd_WriteData(0x0C); Lcd_WriteData(0x31); Lcd_WriteData(0x36); Lcd_WriteData(0x0F); Lcd_WriteIndex(0x11); //Exit Sleep delay_ms(120); Lcd_WriteIndex(0x29); //Display on Lcd_WriteIndex(0x2c); }/*************************************************函数名:LCD_Set_Region功能:设置lcd显示区域,在此区域写点数据自动换行入口参数:xy起点和终点,Y_IncMode表示先自增y再自增x返回值:无*************************************************/void Lcd_SetRegion(u16 x_start,u16 y_start,u16 x_end,u16 y_end){ Lcd_WriteIndex(0x2a); Lcd_WriteData16Bit(x_start>>8,x_start); Lcd_WriteData16Bit(x_end>>8,x_end); Lcd_WriteIndex(0x2b); Lcd_WriteData16Bit(y_start>>8,y_start); Lcd_WriteData16Bit(y_end>>8,y_end); Lcd_WriteIndex(0x2c);}void Lcd_SetXY(u16 x,u16 y){ Lcd_WriteIndex(0x2a); Lcd_WriteData16Bit(x>>8,x); Lcd_WriteIndex(0x2b); Lcd_WriteData16Bit(y>>8,y); Lcd_WriteIndex(0x2c);} /*************************************************函数名:LCD_DrawPoint功能:画一个点入口参数:无返回值:无*************************************************/void Gui_DrawPoint(u16 x,u16 y,u16 Data){ Lcd_SetXY(x,y); Lcd_WriteData(Data>>8); Lcd_WriteData(Data);} /*************************************************函数名:Lcd_Clear功能:全屏清屏函数入口参数:填充颜色COLOR返回值:无*************************************************/void Lcd_Clear(u16 Color) { unsigned int i,m; Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1); LCD_RS_SET; for(i=0;i<Y_MAX_PIXEL;i++) { for(m=0;m<X_MAX_PIXEL;m++) { SPI_WriteByte(Color>>8); SPI_WriteByte(Color); } } // LCD_CS_SET; }void Lcd_WriteData_16Bit(u16 Data){ Lcd_WriteData(Data>>8); Lcd_WriteData(Data);}好长的代码;来看看显示效果吧,还是挺赞的:
|
|