打印
[STM32F1]

stm32F103C8T6核心板使能spi接口显示屏

[复制链接]
583|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ead5ah|  楼主 | 2024-1-31 13:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本次实验所使用的显示屏是使用ST7735S驱动的,ST7735S的驱动芯片手册有两百多页,拿到这个驱动手册后,我们需要关注的是通过我们的核心板给显示屏传输数据时的时序图,以及可以向显示屏传输的命令有哪些?



看时序图是为了能够在配置spi时,根据显示屏的需要来设置参数,我用的显示屏是用三线来进行spi通信的,也就是CS,SCL,和SDA,其他引脚还有DC(用来选择传入的是命令还是图像数据),RES(复位),如下表,其中BL引脚没用到。





使用特权

评论回复
沙发
ead5ah|  楼主 | 2024-1-31 13:58 | 只看该作者
下图是芯片的写操作时序,首先,可以看出空闲时,SCL为低电平,当需要进行写入数据时,我们首先需要设置CS引脚为低电平(使能从设备接收数据),接下来将SCL引脚的输出由空闲状态的0变为1,此时,SDA引脚的的数据就会被写到显示屏中(每次写进一位二进制到接收端的移位寄存器中,当移位寄存器的数据满了,就会自动将移位寄存器的内容存入到接收端的接收缓冲区中)。

使用特权

评论回复
板凳
ead5ah|  楼主 | 2024-1-31 13:59 | 只看该作者
根据时序图来配置stm32核心板的spi外设:

配置SPI为主模式:

配置步骤:

1. 通过 SPI_CR1 寄存器的 BR[2:0] 位定义串行时钟波特率。(数据传输速度,下图中fPCLK为spi所在的时钟总线的时钟频率,SPI1在APB2时钟总线上)


使用特权

评论回复
地板
ead5ah|  楼主 | 2024-1-31 13:59 | 只看该作者
2. 选择 CPOL 和 CPHA 位,定义数据传输和串行时钟间的相位关系 。如下图,这就是配置我们刚才时序图中说到的SCL空闲时钟和SCL由低变高时将数据读入,这里我们配置CPHA=0,CPOL=0;如果接收端的时序要求是其他就按照其他来配置。

使用特权

评论回复
5
ead5ah|  楼主 | 2024-1-31 14:00 | 只看该作者
3. 设置 DFF 位来定义 8 位或 16 位数据帧格式。这里我们设置为8位。
4. 配置 SPI_CR1 寄存器的 LSBFIRST 位定义帧格式。先发送MSB的意思是先发送高位,比如发送10101010,从左往右发送;而先发送LSB 则相反。这里我们设置为先发送MSB。


使用特权

评论回复
6
ead5ah|  楼主 | 2024-1-31 14:00 | 只看该作者
5. 如果需要 NSS 引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应把 NSS 脚连接
到高电平;在软件模式下,需设置 SPI_CR1 寄存器的 SSM 位和 SSI 位。如果 NSS 引脚工作
在输出模式,则只需设置 SSOE位。
在硬件模式下,其实就是硬件自动控制片选CS的高低电平,不需要我们通过程序来设定;而软件模式下,每次发送数据时,就要把CS置为0,意味着从设备被使能,可以向它发送数据,发完后我们又通过程序关闭使能。数据手册说置为软件模式时,要通过SSOE为来控制NSS(也就是CS)来设置引脚的输出,但是我在实验中没用stm32中特定的CS引脚,随便找了一个普通的IO口,直接用GPIOB->BRR和GPIOB->BSRR来设置输出。

6. 必须设置 MSTR 位(设定核心板为主设备)和 SPE 位 ( 只当 NSS 脚被连到高电平,这些位才能保持置位 ) 。

void SPI1Init()
{
        RCC->APB2ENR|=1<<2;          //PORTB时钟使能          
        RCC->APB2ENR|=1<<12;           //SPI2时钟使能
        //这里只针对SPI口初始化
        GPIOA->CRL&=0X000FFFFF;
        GPIOA->CRL|=0XBBB00000;        //PB13/14/15复用             
        GPIOA->ODR&=~(0X7<<5);           //PB13/14/15上拉
        //PI1->CR1|=1<<15;
        SPI1->CR1|=0<<10;                //全双工模式       
        SPI1->CR1|=1<<9;                 //软件nss管理
        SPI1->CR1|=1<<8;  
       
        SPI1->CR1|=1<<2;                 //SPI主机
        SPI1->CR1|=0<<11;                //8bit数据格式       
        SPI1->CR1|=0<<1;                 //空闲模式下SCK为0 CPOL=0
        SPI1->CR1|=0<<0;                 //数据采样从第1个时间边沿开始,CPHA=0  
        //对SPI2属于APB1的外设.时钟频率最大为36M.
        SPI1->CR1|=2<<3;                 //
        SPI1->CR1|=0<<7;                 //MSBfirst  
        SPI1->CR1|=1<<6;                 //SPI设备使能
        //SPI1_ReadWriteByte(0xff);
}

void SPI1_ReadWriteByte(u8 TxData)
{
        while((SPI1->SR&1<<1)==0) //等待发送区空
        {
               
        }
        SPI1->DR=TxData; //发送一个 byte
        delay_us(5);
}

使用特权

评论回复
7
ead5ah|  楼主 | 2024-1-31 14:01 | 只看该作者
注意:在使用PB13,14,15作为spi通信接口时,由于空闲时间SCL为低,所以在配置这三个口初始电平时应配置为低电平,否则可能导致第一个帧数据就发送出错,我自己被这一步折磨了好久,一直没找出来原因。再者,在void SPI1_ReadWriteByte(u8 TxData)中,将数据放到SPI1->DR中后要加一个延时,确保数据成功发出。
————————————————
配置完spi后,就是按照显示屏驱动手册中的指令来控制显示屏以及传入图像数据。
//发送字节(8bit)函数
void SendByte(unsigned char data)
{
        SPI1_ReadWriteByte(data);
}

//发送图像数据函数
void lcd_SendData(unsigned char data)
{
        //DC接口设置为高电平时,SDA接口传入的为数据
        lcd_DC_1;//设置DC接口为高电平
        SPI_CS_0;
        SendByte(data);
        SPI_CS_1;
}
//lcd_DC_1;是用来设置DC引脚为高电平。SPI_CS_0是用来设置CS引脚为低电平
//都是普通io口的设置,方法如下:其他的根据例子自己定义
//#define SPI_CS_0 GPIOB->BRR=0x1000
//#define SPI_CS_1 GPIOB->BSRR=0x1000

使用特权

评论回复
8
ead5ah|  楼主 | 2024-1-31 14:01 | 只看该作者
//发送命令函数
void lcd_SendCmd(unsigned char cmd)
{
        //DC接口设置为低电平时,SDA接口传入的为命令
        lcd_DC_0;//设置DC接口为低电平
        SPI_CS_0;
        SendByte(cmd);
        SPI_CS_1;
}

使用特权

评论回复
9
ead5ah|  楼主 | 2024-1-31 14:02 | 只看该作者
接下来就是根据驱动手册和上面几个函数,对显示屏进行初始化操作,这里我在某宝上买的时候搭配的例程直接拿来用就不贴出来了。

使用特权

评论回复
10
lichenc| | 2024-5-10 15:15 | 只看该作者
感谢提示,我也是"所以在配置这三个口初始电平时应配置为低电平"卡了,调了半天,加上这句话就好了

使用特权

评论回复
11
Bowclad| | 2024-5-12 23:36 | 只看该作者
这个屏幕驱动起来效果怎么样

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

86

帖子

1

粉丝