打印
[USB芯片]

【CH32X035评估版评测】+ 教你使用SPI+DMA驱动GC9A01圆形屏

[复制链接]
2671|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 袁胜富 于 2023-9-11 22:30 编辑

#申请原创# #有奖活动# #技术资源# #申请开发板# @21小管家 一、概述  


        CH32X035的SPI只有一个,那就是SPI1,挂载在APB2总线,最大时钟48MHz。SPI支持单工发送和双工发送,在GC9A01驱动中使用单工主机模式。使用SPI+DMA的方式进行数据的发送,可以使屏幕的刷新更快,本人使用IO模拟SPI和硬件SPI来驱动GC9A01效果都不理想,唯有使用SPI+DMA才能使我满意。
       于是乎为了和大家分享,我出了这个文章。

二、原理分析和硬件连接

      原理分析
      DMA的中文叫直接内存访问,在数据处理上不需要MCU的参与,可以减小MCU的压力。在此次应用中只需要SPI1的发送DMA通道参与。从手册的DMA请求映像来        看,SPI1_TX的要硬件请求在DMA的通道3.

       硬件连接

          RST------->PA3
          CS--------->PA4
          DC--------->PA1
           MOSI--------->PA7
           SCK--------->PA5
           VCC--------->VCC
           GND--------->GND

三、代码

         这里只说明SPI和DMA的配置,详细的代码在上传在附件中。
         SPI初始化
void SPI1_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
SPI_InitTypeDefSPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;//只发送模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//设置SPI工作模式:主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//设置SPI数据大小:8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//串行同步时钟空闲时SCLK位高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//串行同步时钟空第二个时钟沿捕获
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//NSS信号由硬件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//波特率预分频值:波特率预分频值为4
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//数据传输高位先行
SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式
SPI_Init(SPI1,&SPI_InitStructure);//初始化SPI
SPI_Cmd(SPI1, ENABLE);//使能SPI
}
DMA的初始化
DMA_InitTypeDefDMA_InitStructure;
u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA传输
DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
}
void MYDMA_Config1(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA传输
DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;  //内存地址寄存器不变
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
}
         以上DMA有两个配置,一个数据宽度为Byte字节,一个是HalfWord半字(两个字节)。因为屏幕的命令是一个字节,而颜色数据则为16位两个字节数据,所以为了快速切换操作数据,才这样配置。

四、展示



        两张图展示屏幕的显示汉字和ASCII字符。
        BiliBili链接:【CH32X035的SPI+DMA驱动GC9A01圆形屏幕-哔哩哔哩】 https://b23.tv/lsc9C7t


五、心得与体会

         总的来看CH32X035的SPI+DMA在屏幕驱动上面应用还是挺不错的。
         谢谢大家,如有不当之处,还望不吝赐教。




LCD取模教程.zip

1.62 MB

CH32X035C8T6_SPIDMA_LCD.zip

712.12 KB

使用特权

评论回复
评论
forgot 2023-9-11 08:25 回复TA
赞 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

159

帖子

2

粉丝