概述
CH32V307系列是基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能。扩展串口UART数量到8组,电机定时器到4组。提供USB2.0高速接口(480Mbps)并内置了PHY收发器,以太网MAC升级到千兆并集成了10M-PHY模块。
系统框图
产品特点
- 青稞V4F处理器,最高144MHz系统主频
- 支持单周期乘法和硬件除法,支持硬件浮点运算(FPU)
- 64KB SRAM,256KB Flash
- 供电电压:2.5/3.3V,GPIO单元独立供电
- 多种低功耗模式:睡眠、停止、待机
- 上/下电复位、可编程电压监测器
- 2组18路通用DMA
- 4组运放比较器
- 1个随机数发生器TRNG
- 2组12位DAC转换
- 2单元16通道12位ADC转换,16路触摸按键TouchKey
- 10组定时器
- USB2.0全速OTG接口
- USB2.0高速主机/设备接口(480Mbps 内置PHY)
- 3个USART接口和5个UART接口
- 2个CAN接口(2.0B主动)
- SDIO接口、FSMC接口、DVP数字图像接口
- 2组IIC接口、3组SPI接口、2组IIS接口
- 千兆以太网控制器ETH(内置10M PHY)
- 80个I/O口,可以映射到16外部中断
- CRC计算单元,96位芯片唯一ID
- 串行2线调试接口
- 封装形式:LQFP64M、LQFP100
开发板原理图
Nokia LCD5110接口
- RST ——复位
- CE —— 片选
- DC —— 数据/指令选择
- DIN —— 串行数据线
- CLK —— 串行时钟线
- VCC —— 电源输入(3.3v和5v均可)
- BL —— 背光控制端
- GND —— 地线
接口控制管脚配置如下
#define sce0 GPIO_WriteBit(GPIOA, GPIO_Pin_2,Bit_RESET) //片选CE
#define res0 GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_RESET) //复位RST,0复位
#define dc0 GPIO_WriteBit(GPIOA, GPIO_Pin_3,Bit_RESET) //DC 1写数据,0写指令
#define sdin0 GPIO_WriteBit(GPIOA, GPIO_Pin_4,Bit_RESET) //数据DIN
#define sclk0 GPIO_WriteBit(GPIOA, GPIO_Pin_5,Bit_RESET) //时钟CLK
#define sce1 GPIO_WriteBit(GPIOA, GPIO_Pin_2,Bit_SET) //片选CE
#define res1 GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_SET) //复位RST,0复位
#define dc1 GPIO_WriteBit(GPIOA, GPIO_Pin_3,Bit_SET) //DC 1写数据,0写指令
#define sdin1 GPIO_WriteBit(GPIOA, GPIO_Pin_4,Bit_SET) //数据DIN
#define sclk1 GPIO_WriteBit(GPIOA, GPIO_Pin_5,Bit_SET) //时钟CLK
#define LINGHT_OFF GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_SET)
#define LINGHT_ON GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_RESET)
程序实现功能说明
1-PA0控制LCD背光灯,为了看到效果,LCD控制背光闪烁2Hz;
2-PA6接入LED2,控制LED灯0.5S亮灭一次;
3-LCD测试显示是否成功,0.5S更新一次计数器并显示。
程序源代码
main函数
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : Main program body.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
/*
*@Note
GPIO例程:
PA0推挽输出。
*/
#include "debug.h"
#include "5110LCD.h"
/* Global define */
/* Global Variable */
/*********************************************************************
* @fn GPIO_Toggle_INIT
*
* [url=home.php?mod=space&uid=2666770]@Brief[/url] Initializes GPIOA.0
*
* [url=home.php?mod=space&uid=1141835]@Return[/url] none
*/
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void GPIO_LCD5110_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 |GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
u8 i = 0;
u16 j=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\\r\\n", SystemCoreClock);
printf("GPIO Toggle and LCD5110 TEST\\r\\n");
GPIO_Toggle_INIT();
GPIO_LCD5110_INIT();
LCD_Init();
LCD_WriteString_en(0,0,"LCD5110 TEST");
LCD_WriteString_en(0,1,"2023-08-27");
LCD_WriteString_en(0,2,"_____________");
LCD_WriteString_en(0,3,"Count:");
while(1)
{
Delay_Ms(500);
LCD_WriteNumber(0,4,j);
j++;
if(i==0){
GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_RESET);
GPIO_WriteBit(GPIOA, GPIO_Pin_6,Bit_RESET);
i=1;
}else{
GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_SET);
GPIO_WriteBit(GPIOA, GPIO_Pin_6,Bit_SET);
i=0;
}
}
}
LCD驱动文件
LCD头文件
#ifndef __5110LCD_H
#define __5110LCD_H
#include "debug.h"
#define sce0 GPIO_WriteBit(GPIOA, GPIO_Pin_2,Bit_RESET)
#define res0 GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_RESET)
#define dc0 GPIO_WriteBit(GPIOA, GPIO_Pin_3,Bit_RESET)
#define sdin0 GPIO_WriteBit(GPIOA, GPIO_Pin_4,Bit_RESET)
#define sclk0 GPIO_WriteBit(GPIOA, GPIO_Pin_5,Bit_RESET)
#define sce1 GPIO_WriteBit(GPIOA, GPIO_Pin_2,Bit_SET)
#define res1 GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_SET)
#define dc1 GPIO_WriteBit(GPIOA, GPIO_Pin_3,Bit_SET)
#define sdin1 GPIO_WriteBit(GPIOA, GPIO_Pin_4,Bit_SET)
#define sclk1 GPIO_WriteBit(GPIOA, GPIO_Pin_5,Bit_SET)
#define LINGHT_OFF GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_SET)
#define LINGHT_ON GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_RESET)
void LCD_WriteByte(uint8_t dt, uint8_t command);
void LCD_Init(void);
void LCD_Set_XY(uint8_t X, uint8_t Y);
void LCD_Clear(void);
void LCD_WriteChar(uint8_t X,uint8_t Y,uint8_t c);
void LCD_WriteString_en(uint8_t X,uint8_t Y,char *s);
void LCD_WriteNumber(uint8_t x,uint8_t y, unsigned long number);
void LCD_Write_cn(uint8_t row, uint8_t page,uint8_t c);
#endif
LCD函数实现
#include "5110LCD.h"
//----------------------------------英文字符库-------------------------------------
// 6 x 8 font
// 1 pixel space at left and bottom
// 位置 = (ASCII - 32)*6
//----------------------------------------------------------------------------------
//****************************************************************************************************
// 英文字符大小
//****************************************************************************************************
#define WIDTH 6
#define HEIGHT 8
//****************************************************************************************************
// 中文字符大小
//****************************************************************************************************
#define WIDTH_CN 13
#define HEIGHT_CN 16
uint8_t lcd_display[]="0123456789";
const uint8_t font[][6] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
{ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !
{ 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
{ 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
{ 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
{ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // %
{ 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
{ 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
{ 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
{ 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
{ 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *
{ 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +
{ 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // ,
{ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
{ 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
{ 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0
{ 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1
{ 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
{ 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3
{ 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4
{ 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
{ 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6
{ 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
{ 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
{ 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9
{ 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
{ 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
{ 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
{ 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
{ 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
{ 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @
{ 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
{ 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F
{ 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G
{ 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
{ 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I
{ 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J
{ 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
{ 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L
{ 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M
{ 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
{ 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q
{ 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R
{ 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
{ 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
{ 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U
{ 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V
{ 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W
{ 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
{ 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
{ 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
{ 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [
{ 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55
{ 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ]
{ 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
{ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
{ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // '
{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d
{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f
{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g
{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h
{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i
{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j
{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k
{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l
{ 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
{ 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p
{ 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r
{ 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t
{ 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u
{ 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v
{ 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w
{ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
{ 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y
{ 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } // horiz lines
};
//****************************************************************************************************
// 写一字节
//****************************************************************************************************
void LCD_WriteByte(uint8_t dt, uint8_t command)
{
uint8_t i;
sce0; //使能LCD
if(command==0) //传送命令
dc0;
else
dc1; //传送数据
for(i=0;i<8;i++)
{
if(dt&0x80)
sdin1;
else
sdin0;
sclk0;
dt=(uint8_t)(dt << 1);
sclk1;
}
dc1;
sce1;//关闭LCD
sdin1;
}
//****************************************************************************************************
// LCD初始化
//****************************************************************************************************
void LCD_Init(void)
{
sce1;
res0;//产生一个让LCD复位的低电平脉冲
//delay_ms(10);
for(int j=0;j<100;j++){for(int i=0;i<4800;i++);} //48M clock,100*0.1ms
res1;
for(int j=0;j<1000;j++){for(int i=0;i<4800;i++);} //48M clock,1000*0.1ms
LCD_WriteByte(0x21,0);//使用水平寻址,进入拓展指令
LCD_WriteByte(0x13,0);//定液晶偏置系统 1:48
LCD_WriteByte(0xbb,0);//设定设置Vop,相当于亮度
LCD_WriteByte(0x20,0);//芯片活动 使用基本指令并且水平寻址
LCD_WriteByte(0x0c,0);//设定显示模式,正常显示
LCD_Clear();
}
//---------------------------------------
//名称: 设置坐标函数
//参数:X:0-83 Y:0-5
//作者:huoenlai
//邮箱:1084170961@qq.com
//日期:2011/3/28
//-----------------------------------------
void LCD_Set_XY(uint8_t X, uint8_t Y)
{
Y|=0x40;
X|=0x80;
LCD_WriteByte(Y, 0);// 列
LCD_WriteByte(X, 0);// 行
sce1;
}
//****************************************************************************************************
// LCD清屏
//****************************************************************************************************
void LCD_Clear(void)
{
uint8_t t,k;
LCD_Set_XY(0,0);
for(t=0;t<6;t++)
{
for(k=0;k<84;k++)
{
LCD_WriteByte(0x00,1);
}
}
}
//****************************************************************************************************
// 写一个字符
//****************************************************************************************************
void LCD_WriteChar(uint8_t X,uint8_t Y,uint8_t c)
{
uint8_t i,j ;
const uint8_t *map = &font[0][0];
c -= 32; //变换
map += c *( HEIGHT/8*WIDTH);
for(i=0;i<HEIGHT/8;i++)
{
LCD_Set_XY(X, Y+i);
for(j=0;j<WIDTH;j++)
LCD_WriteByte(*map++, 1);
}
}
//****************************************************************************************************
// 写英文字符串
//****************************************************************************************************
void LCD_WriteString_en(uint8_t X,uint8_t Y,char *s)
{
uint8_t i=0,j=0;
while (*s)
{
LCD_WriteChar(X, Y,*s++);
X+=WIDTH;
i++;
if(i>=(84/WIDTH))
{
X=0;
Y+=HEIGHT;
i=0;
j++;
}
if(j>=(48/HEIGHT))
{
return ;
}
}
}
//****************************************************************************************************
// 写一个任意数字
//****************************************************************************************************
void LCD_WriteNumber(uint8_t x,uint8_t y, unsigned long number)
{
uint8_t num[10]={""},i,j,k;
if(number==0) //number 0 时候
{
LCD_WriteChar(x, y,'0');
}
else
{
for(i=0;number>0;i++)
{
num[i]=lcd_display[number%10];//每位以字符表示
number/=10;
}
for(j=0;j<i/2;j++){k=num[j];num[j]=num[i-1-j];num[i-1-j]=k;}
LCD_WriteString_en(x,y,num);
}
}
//****************************************************************************************************
实际运行效果
开机前
开机后
程序运行视频
见附件