打印
[PIC®/AVR®/dsPIC®产品]

大家一起来攻克PIC18F单片机的MCC配置SPI驱动TFT难题——已经搞定

[复制链接]
11850|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 gaoyang9992006 于 2024-7-30 21:57 编辑

不好意思,我在用MCC配置SPI驱动TFT显示屏(ST7735S)的时候,失手了。
没能驱动起来。
我用的是PIC18F16Q41 curiosity NANO开发板
为了方便供电和插飞线,我用IO代替的VCC给小屏供电,以及给背光供电。
SPI_ST7735S.X.rar (43.84 KB)
有问题的工程放这个附件压缩包里了。大家可以下载测试,找出问题在哪儿
程序结构讲解
ST7735的相关文件有4个,其中2个是关键文件st7735.c 和 st7735.h
.h中仅仅用于引入MCC配置的系统文件头文件和延时函数头文件。
在.c中实现了接口

void ST7735_delay(uint8_t i)
{
        DELAY_microseconds(i);
}

void ST7735_SPI_SendByte(uint8_t byte)
{
    SPI1_ByteWrite(byte);
    while (SPI1_IsTxReady()==false);
}

void ST7735_SPI_RST_SetLow(void)
{
    RST_SetLow();
}
void ST7735_SPI_RST_SetHigh(void)
{
    RST_SetHigh();
}

void ST7735_SPI_CS_SetLow(void)
{
    CS_SetLow();
}
void ST7735_SPI_CS_SetHigh(void)
{
    CS_SetHigh();
}

void ST7735_SPI_DC_SetLow(void)
{
    DC_SetLow();
}
void ST7735_SPI_DC_SetHigh(void)
{
    DC_SetHigh();
}
目前运行的时候会卡在函数
void ST7735_SPI_SendByte(uint8_t byte)
{
    SPI1_ByteWrite(byte);
    while (SPI1_IsTxReady()==false);
}
的while循环里。
不知道为何?
另外在MCC配置SPI的时候确实不知道4个模式是什么意思,如下:

默认的是Mode1,我也尝试切换到其他模式,也是卡死,无法正常点亮屏幕。
我在其他ARM核心单片机测试过这个ST7735的库,是可以用的。

搞定方法:https://bbs.21ic.com/icview-3393320-1-1.html

使用特权

评论回复
沙发
gaoyang9992006|  楼主 | 2024-7-22 15:58 | 只看该作者
恳求各位大佬有条件的测试一下,帮忙检查一下,看看如何在MCC里使用好PIC18F的SPI来驱动显示屏。

使用特权

评论回复
板凳
gaoyang9992006|  楼主 | 2024-7-22 16:34 | 只看该作者
ST7735的程序本身是没问题的,我将SPI发送函数换成IO模拟就可以正常点亮。
所以问题应该是SPI没有配置正确
void LCD_Writ_Bus(uint8_t dat) 
{       
        uint8_t i;
        for(i=0;i<8;i++)
        {                          
        SCK_SetLow();
                if(dat&0x80)
                {
           SDO_SetHigh();
                }
                else
                {
           SDO_SetLow();
                }
        SCK_SetHigh();
                dat<<=1;
        }
}

void ST7735_SPI_SendByte(uint8_t byte)
{
//    SPI1_ByteWrite(byte);
//    while (SPI1_IsTxReady()==false);
    LCD_Writ_Bus(byte);
}
上述是切换成IO模拟的实现代码,是可以正常工作的。

使用特权

评论回复
地板
lcczg| | 2024-7-22 17:38 | 只看该作者
4个模式选择的是SPI CON1里的CKE CKP:
      CKE      CKP
0:   1         0
1:   0         0
2:   1         1
3:   0         1
控制采样时钟,可以看数据手册图35-7  35-9

使用特权

评论回复
5
gaoyang9992006|  楼主 | 2024-7-22 19:21 | 只看该作者
lcczg 发表于 2024-7-22 17:38
4个模式选择的是SPI CON1里的CKE CKP:
      CKE      CKP
0:   1         0

再看看为何发送函数一直卡,

使用特权

评论回复
6
wanduzi| | 2024-7-22 20:52 | 只看该作者
期待楼主能解决这个问题。

使用特权

评论回复
7
xinxianshi| | 2024-7-22 22:26 | 只看该作者
SPI(Serial Peripheral Interface)是一种常见的串行通信协议,用于在微控制器、传感器、存储器等设备之间进行通信。SPI控制器支持的主要模式包括模式0到模式3,它们主要区别在于时钟极性(CPOL)和时钟相位(CPHA)的不同设置。

这里是对SPI控制器支持的模式0到模式3的简要介绍:

模式0:

CPOL = 0,CPHA = 0
时钟极性为低电平(时钟信号空闲时为低电平),时钟相位在第一个时钟边沿进行数据采样。
数据在时钟的上升沿采样,下降沿更新。
模式1:

CPOL = 0,CPHA = 1
时钟极性为低电平,时钟相位在第二个时钟边沿进行数据采样。
数据在时钟的下降沿采样,上升沿更新。
模式2:

CPOL = 1,CPHA = 0
时钟极性为高电平(时钟信号空闲时为高电平),时钟相位在第一个时钟边沿进行数据采样。
数据在时钟的下降沿采样,上升沿更新。
模式3:

CPOL = 1,CPHA = 1
时钟极性为高电平,时钟相位在第二个时钟边沿进行数据采样。
数据在时钟的上升沿采样,下降沿更新。
在SPI通信中,选择使用哪种模式取决于具体的硬件和通信需求。不同的设备可能要求不同的模式来进行正确的通信,特别是在速率高、数据精确性要求高的情况下。

使用特权

评论回复
8
xinxianshi| | 2024-7-22 22:26 | 只看该作者
我猜模式可能是上面这个内容。不过怎么卡死,不知道。

使用特权

评论回复
9
lcczg| | 2024-7-23 09:39 | 只看该作者
本帖最后由 lcczg 于 2024-7-23 09:49 编辑
gaoyang9992006 发表于 2024-7-22 19:21
再看看为何发送函数一直卡,

卡死有两种可能。EN和TXIF的问题。
bool SPI1_IsTxReady(void)
{
        bool returnValue = false;
        if(true == SPI1CON0bits.EN)
        {
                returnValue = PIR3bits.SPI1TXIF;
        }
        else
        {
                returnValue = false;
        }
        return returnValue;
}
假设是发送FIFO满的时候SPI TXIF清零的情况导致堵塞。但理论上最终也会发出去的,堵塞会清除。

你测一下看看是EN还是TXIF的问题?

使用特权

评论回复
10
gaoyang9992006|  楼主 | 2024-7-23 10:20 | 只看该作者
lcczg 发表于 2024-7-23 09:39
卡死有两种可能。EN和TXIF的问题。
bool SPI1_IsTxReady(void)
{

TXIF一直是0
我用MCC配置的,工程在附件里,你看看。

使用特权

评论回复
11
lcczg| | 2024-7-23 16:41 | 只看该作者
本帖最后由 lcczg 于 2024-7-23 16:42 编辑
gaoyang9992006 发表于 2024-7-23 10:20
TXIF一直是0
我用MCC配置的,工程在附件里,你看看。

我重现了这个现象。
调试发现根本的原因在于模式的设置, 在函数void SPI1_ByteWrite(uint8_t byteData)中,
SPI1CON2 = SPI1CON2 | _SPI1CON2_SPI1RXR_MASK | _SPI1CON2_SPI1TXR_MASK;
上述代码使能了发送和接收的FIFO。即便你只使用了发送FIFO,仍然需要处理接收FIFO。
堵塞的原因在于没有处理接收FIFO,导致满了FULL,导致传输中断,发送也就中断了。
数据手册里有描述:

在你的应用中只有发送,所以只需使能发送FIFO即可。
SPI1CON2 = SPI1CON2 | _SPI1CON2_SPI1TXR_MASK;

使用特权

评论回复
12
gaoyang9992006|  楼主 | 2024-7-23 17:02 | 只看该作者
lcczg 发表于 2024-7-23 16:41
我重现了这个现象。
调试发现根本的原因在于模式的设置, 在函数void SPI1_ByteWrite(uint8_t byteData)中 ...

好,我试试看,那个函数体是MCC自动生成的。发现新版的MCC里面配置这个SPI,几乎没什么选项可配置的。

使用特权

评论回复
13
gaoyang9992006|  楼主 | 2024-7-23 19:39 | 只看该作者
lcczg 发表于 2024-7-23 16:41
我重现了这个现象。
调试发现根本的原因在于模式的设置, 在函数void SPI1_ByteWrite(uint8_t byteData)中 ...

试了一下,这个设置确实可以解决卡死。
但是没点亮屏幕。电路不变,程序其他都不变,换成IO模拟的就可以。不知道问题在哪儿了。

使用特权

评论回复
14
稳稳の幸福| | 2024-7-23 21:08 | 只看该作者
什么时候点亮屏幕分享一下啊。

使用特权

评论回复
15
guijial511| | 2024-7-24 08:04 | 只看该作者
没点亮屏幕,说明驱动时序或者寄存器配置还是有点问题。

使用特权

评论回复
16
lcczg| | 2024-7-24 10:00 | 只看该作者
gaoyang9992006 发表于 2024-7-23 19:39
试了一下,这个设置确实可以解决卡死。
但是没点亮屏幕。电路不变,程序其他都不变,换成IO模拟的就可以 ...

比较下两种配置下SPI输出的波形。

使用特权

评论回复
17
gaoyang9992006|  楼主 | 2024-7-24 10:50 | 只看该作者
guijial511 发表于 2024-7-24 08:04
没点亮屏幕,说明驱动时序或者寄存器配置还是有点问题。

没有问题,只是SPI发送函数本身没发出来任何东西。。。换成IO模拟的函数就可以正常,工作,在STM32,新唐,CW,等多种单片机上测试过都是一次点亮。

使用特权

评论回复
18
gaoyang9992006|  楼主 | 2024-7-24 10:50 | 只看该作者
lcczg 发表于 2024-7-24 10:00
比较下两种配置下SPI输出的波形。

示波器观察了,没有波形输出。。。

使用特权

评论回复
19
lcczg| | 2024-7-24 14:40 | 只看该作者
本帖最后由 lcczg 于 2024-7-24 14:54 编辑

gaoyang9992006 发表于 2024-7-24 10:50
示波器观察了,没有波形输出。。。

我这里可以看到的。


IMG_5505[1].JPG (343.57 KB )

IMG_5505[1].JPG

使用特权

评论回复
20
gaoyang9992006|  楼主 | 2024-7-24 15:12 | 只看该作者
lcczg 发表于 2024-7-24 14:40
我这里可以看到的。

你的工程打包分享一下我对比一下。

使用特权

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

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1950

主题

15888

帖子

206

粉丝