IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> GPIO 模拟SPI -> 正文阅读

[嵌入式]GPIO 模拟SPI

SPI简介

SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)。

  • SDO(MOSI): 主设备数据输出,从设备数据输入
  • SDI(MISO):主设备数据输入,从设备数据输出
  • SCLK : 时钟信号,由主设备产生
  • CS :从设备使能信号,由主设备控制

SCPH=0,SCPOL=0 的 SPI 协议时序图在这里插入图片描述

SCPH=1,SCPOL=0 的 SPI 协议时序图

在这里插入图片描述

SCPH=0,SCPOL=1 的 SPI 协议时序图

在这里插入图片描述

SCPH=1,SCPOL=1 的 SPI 协议时序图

在这里插入图片描述

GPIO模拟

定义出MISO、MOSI、CS、CLK等

#define CS_GPIO                       (0)
#define CLK_GPIO                      (1)
#define MOSI_GPIO                     (2)
#define MISO_GPIO                     (3)
#define IRQ_GPIO                      (4)

#define CS(a)                         Set_SPI_Related_Gpio(a, CS_GPIO)
#define DCLK(a)                       Set_SPI_Related_Gpio(a, CLK_GPIO)
#define DIN(a)                        Set_SPI_Related_Gpio(a, MOSI_GPIO)
#define DOUT()                        Get_SPI_Related_Gpio(MISO_GPIO)

往从设备发送数据

/**
  * @brief  Write Byte to LCD
  * @param  byte : Byte
  */
void WriteByteSPI(unsigned char byte)
{
    unsigned char buf;
    unsigned char i;
    CS(0);
    for(i=0;i<8;i++) 
    {
        buf=(byte>>(7-i))&0x1;
        DIN(buf);
        DCLK(0);
        DCLK(1);
    }	
    CS(1);
}

从设备读取数据

/**
  * @brief  Read data from spi
  */
static unsigned short ReadByteSPI(void) 
{
    unsigned short buf=0,temp;
    unsigned char i;
    uint level = 0;
    DIN(0);
    DCLK(1);
    CS(0);
    for(i=0;i<8;i++)
    {
        DCLK(0);
        level = DOUT();
        temp= (level) ? 1:0;
        buf|=(temp<<(7-i));
        //Delayus(5);
        DCLK(0);
        DCLK(1);
    }
    CS(1);
    buf&=0xff;
    return(buf);
}

stm32上完整demo

//LCD.h
#include "HAL_conf.h"

#define SPI_CS(a)	\
						if (a)	\
						GPIOA->BSRR = GPIO_Pin_4;	\
						else		\
						GPIOA->BRR = GPIO_Pin_4;
#define SPI_DCLK(a)	\
						if (a)	\
						GPIOA->BSRR = GPIO_Pin_5;	\
						else		\
						GPIOA->BRR = GPIO_Pin_5;
#define SPI_SDA(a)	\
						if (a)	\
						GPIOA->BSRR = GPIO_Pin_7;	\
						else		\
						GPIOA->BRR = GPIO_Pin_7;
#define lcd_RS(a)	\
						if (a)	\
						GPIOA->BSRR = GPIO_Pin_3;	\
						else		\
						GPIOA->BRR = GPIO_Pin_3;

#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 //灰色

void LCD_Initial(void); //LCD初始化函数
void Delayms(unsigned short time);
void LCD_WriteRegIndex(unsigned char Index);
void LCD_WriteData(unsigned short dat);
void LCD_WR_REG(u16 Index,u16 CongfigTemp);
void Lcd_SetCursor(u16 x,u16 y);
void SPILCD_SetWindow(unsigned short xstat,unsigned short xend,unsigned short ystat,unsigned short yend);
void SPILCD_DrawPoint(unsigned short x,unsigned short y,unsigned short color);
void SPILCD_Clear(unsigned short Color);
void SPILCD_Clear_Fast(unsigned char single_Color);
void SPILCD_Fill(unsigned short xsta,unsigned short ysta,unsigned short xend,unsigned short yend,unsigned short color);
void SPILCD_DrawLine(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned short color);
void SPILCD_ShowChar(unsigned short x,unsigned short y,unsigned char num, unsigned int fColor, unsigned int bColor,unsigned char flag) ;
void LCD_PutString(unsigned short x, unsigned short y, char *s, unsigned int fColor, unsigned int bColor,unsigned char flag);
void LCD_Fill_Pic(u16 x, u16 y,u16 pic_H, u16 pic_V, const unsigned char* pic);

//LCD.c
#include "LCD.h"
#include "ASCII.h"
#include "GB1616.h"	//16*16汉字字模
#define SPILCD_W 176
#define SPILCD_H 220

void Delayms(unsigned short time)  //延时函数
{
	unsigned short i,j;
	for(i=0;i<time;i++)
		for(j=0;j<5000;j++)	;
}

void LCD_WriteByteSPI(unsigned char byte) //SPI模拟函数,写一个8bit的数据
{
	  unsigned char buf;
    unsigned char i;
    for(i=0;i<8;i++) 
    {
        buf=(byte>>(7-i))&0x1;
        SPI_SDA(buf);
				SPI_DCLK(0);
        SPI_DCLK(1);
    }	
}
void LCD_WriteoneSPI(unsigned char byte) //写一个4bit的数据
{
	  unsigned char buf;
    unsigned char i;
	
    for(i=0;i<4;i++) 
    {
        buf=(byte>>(3-i))&0x1;
        SPI_SDA(buf);
				SPI_DCLK(0);
        SPI_DCLK(1);
    }	

}
void WriteComm(unsigned char dat) //写命令
{
//	SPI_CS(0);
	lcd_RS(0);
	LCD_WriteByteSPI(dat);	
	lcd_RS(1);
//	SPI_CS(1);
}
void LCD_WriteRegIndex(unsigned char Index) //写命令的参数
{
	lcd_RS(0);
	LCD_WriteByteSPI(Index);
	lcd_RS(1);
}
void LCD_WriteData(unsigned short dat) //写数据
{
  LCD_WriteByteSPI(dat>>8);		//	start byte RS=1,RW=0----Write a GRAM data
  LCD_WriteByteSPI(dat);
}
/******************************************
函数名:Lcd写命令函数
功能:向Lcd指定位置写入应有命令或数据
入口参数:Index 要寻址的寄存器地址
          ConfigTemp 写入的数据或命令值
******************************************/
void LCD_WR_REG(u16 Index,u16 CongfigTemp)
{
	LCD_WriteRegIndex(Index);
	LCD_WriteByteSPI(CongfigTemp);
//LCD_WriteData(CongfigTemp);
}

void LCD_Initial(void) //LCD初始化函数
{

	GPIO_SetBits(GPIOA, GPIO_Pin_2);//打开背光

		//Power Voltage Setting 
LCD_WR_REG(0x1A,0x02);     //BT 
LCD_WR_REG(0x1B,0x88);     //VRH 
 
//****VCOM offset**/// 
LCD_WR_REG(0x23,0x00);     //SEL_VCM 
LCD_WR_REG(0x24,0xEE);     //VCM 
LCD_WR_REG(0x25,0x15);     //VDV 
 
LCD_WR_REG(0x2D,0x03);     //NOW[2:0]=011 
 
//Power on Setting 
LCD_WR_REG(0x18,0x1E);     //Frame rate 72Hz 
LCD_WR_REG(0x19,0x01);     //OSC_EN='1', start Osc 
LCD_WR_REG(0x01,0x00);     //DP_STB='0', out deep sleep 
LCD_WR_REG(0x1F,0x88);    //STB=0 
Delayms(5); 
LCD_WR_REG(0x1F,0x80);      //DK=0 
Delayms(5); 
LCD_WR_REG(0x1F,0x90);    //PON=1 
Delayms(5); 
LCD_WR_REG(0x1F,0xD0);    //VCOMG=1 
Delayms(5); 
 LCD_WR_REG(0x2F,0x00);
//262k/65k color selection 
LCD_WR_REG(0x17,0x05);     //default 0x06 262k color // 0x05 65k color 
 
//SET PANEL 
LCD_WR_REG(0x16,0xA0);
LCD_WR_REG(0x36,0x09);     //REV_P, SM_P, GS_P, BGR_P, SS_P 
LCD_WR_REG(0x29,0x31);     //400 lines 
LCD_WR_REG(0x71,0x1A);     //RTN 

//Gamma 2.2 Setting     
 LCD_WR_REG(0x40,0x01); 
 LCD_WR_REG(0x41,0x08); 
 LCD_WR_REG(0x42,0x04); 
 LCD_WR_REG(0x43,0x2D); 
 LCD_WR_REG(0x44,0x30); 
 LCD_WR_REG(0x45,0x3E); 
 LCD_WR_REG(0x46,0x02); 
 LCD_WR_REG(0x47,0x69); 
 LCD_WR_REG(0x48,0x07); 
 LCD_WR_REG(0x49,0x0E); 
 LCD_WR_REG(0x4A,0x12); 
 LCD_WR_REG(0x4B,0x14); 
 LCD_WR_REG(0x4C,0x17); 
 
 LCD_WR_REG(0x50,0x01); 
 LCD_WR_REG(0x51,0x0F); 
 LCD_WR_REG(0x52,0x12); 
 LCD_WR_REG(0x53,0x3B); 
 LCD_WR_REG(0x54,0x37); 
 LCD_WR_REG(0x55,0x3E); 
 LCD_WR_REG(0x56,0x16); 
 LCD_WR_REG(0x57,0x7D); 
 LCD_WR_REG(0x58,0x08); 
 LCD_WR_REG(0x59,0x0B); 
 LCD_WR_REG(0x5A,0x0D); 
 LCD_WR_REG(0x5B,0x11); 
 LCD_WR_REG(0x5C,0x18); 
 LCD_WR_REG(0x5D,0xFF); 
 
LCD_WR_REG(0x1B,0x001a); //VRH 
LCD_WR_REG(0x25,0x0055); //NVRH 
LCD_WR_REG(0x1A,0x0010); //BT 
LCD_WR_REG(0x1E,0x0038); //FS1   

//Display ON Setting 
LCD_WR_REG(0x28,0x38);      //GON=1, DTE=1, D=10 
Delayms(40); 
LCD_WR_REG(0x28,0x3C);      //GON=1, DTE=1, D=11 
 
WriteComm(0x22);               //Start GRAM write 
}




/*************************************************
函数名:Lcd光标起点定位函数
功能:指定320240液晶上的一点作为写数据的起始点
入口参数:x 坐标 0~239
          y 坐标 0~319
返回值:无
*************************************************/
void Lcd_SetCursor(u16 x,u16 y)
{ 
  LCD_WriteRegIndex(0x20);
  LCD_WriteData(x);//水平坐标
  LCD_WriteRegIndex(0x21);
  LCD_WriteData(y);//垂直坐标 
} 
void SPILCD_SetWindow(unsigned short xstat,unsigned short xend,unsigned short ystat,unsigned short yend)
{
	//Set GRAM Area 
	LCD_WR_REG(0x02,xstat>>8); 
	LCD_WR_REG(0x03,xstat&0xff);     //Column Start 
	LCD_WR_REG(0x04,xend>>8); 
	LCD_WR_REG(0x05,xend&0xff);     //Column End 
	 
	LCD_WR_REG(0x06,ystat>>8); 
	LCD_WR_REG(0x07,ystat&0xff);     //Row Start 
	LCD_WR_REG(0x08,yend>>8); 
	LCD_WR_REG(0x09,yend&0xff);     //Row End 

	WriteComm(0x22);
}
void SPILCD_Fill(unsigned short xsta,unsigned short ysta,unsigned short xend,unsigned short yend,unsigned short color)
{                    
	unsigned short i,j;
	//设置窗口		
	SPILCD_SetWindow(xsta,xend-1,ysta,yend-1);
	for(i=xsta;i<=xend;i++)
		for(j=ysta;j<=yend;j++)
	{
		   	LCD_WriteData(color);	  //显示所填充的颜色. 
	}    
}
/******************************************
函数名:Lcd图像填充100*100
功能:向Lcd指定位置填充图像
入口参数:
******************************************/
void LCD_Fill_Pic(u16 x, u16 y,u16 pic_H, u16 pic_V, const unsigned char* pic)
{
  unsigned long i,j;
	j=pic_H*pic_V*2;
	SPILCD_SetWindow(x,x+pic_H-1,y,y+pic_V-1);
	for (i = 0; i < j; i++)
	{
    LCD_WriteByteSPI(pic[i]);
	}
}
//=============== 在x,y 坐标上打一个颜色为Color的点 ===============
void DrawPixel(u16 x, u16 y, int Color)
{
	SPILCD_SetWindow(x,x,y,y); 
  LCD_WriteData(Color);							  
}
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
//8*16字体 ASCII码 显示
//函数名:SPILCD_ShowChar
//参  数:
//(x,y): 
//num:要显示的字符:" "--->"~"
//flag:有背景色(1)无背景色(0)
void SPILCD_ShowChar(unsigned short x,unsigned short y,unsigned char num, unsigned int fColor, unsigned int bColor,unsigned char flag) 
{       
	unsigned char temp;
	unsigned int pos,i,j;  

	num=num-' ';//得到偏移后的值
	i=num*16; 	
	for(pos=0;pos<16;pos++)
		{
			temp=nAsciiDot[i+pos];	//调通调用ASCII字体
			for(j=0;j<8;j++)
		   {                 
		        if(temp&0x80)
							DrawPixel(x+j,y,fColor);
						else 
							if(flag) DrawPixel(x+j,y,bColor); //如果背景色标志flag为1
							temp<<=1; 
		    }
			 y++;
		}		 
}  

//写一个16x16的汉字
void PutGB1616(unsigned short x, unsigned short  y, unsigned char c[2], unsigned int fColor,unsigned int bColor,unsigned char flag)
{
	unsigned int i,j,k;
	unsigned short m;
	for (k=0;k<64;k++) { //64标示自建汉字库中的个数,循环查询内码
	  if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1]))
			{ 
    	for(i=0;i<32;i++) 
			{
				m=codeGB_16[k].Msk[i];
				for(j=0;j<8;j++) 
				{		
					if((m&0x80)==0x80) {
						DrawPixel(x+j,y,fColor);
						}
					else {
						if(flag) DrawPixel(x+j,y,bColor);
						}
					m=m<<1;
				} 
				if(i%2){y++;x=x-8;}
				else x=x+8;
		  }
		}  
	  }	
	}

//显示一串字
void LCD_PutString(unsigned short x, unsigned short y, char *s, unsigned int fColor, unsigned int bColor,unsigned char flag) 
{
	unsigned char l=0;
	while(*s) 
		{
			if( *s < (char)0x80) 
					{
						SPILCD_ShowChar(x+l*8,y,*s,fColor,bColor,flag);
						s++;l++;
					}
			else
					{
						PutGB1616(x+l*8,y,(unsigned char*)s,fColor,bColor,flag);
						s+=2;l+=2;
					}
		}
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:31:28  更:2022-10-22 21:33:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 17:46:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码