基于ch32开发的智能门锁第二讲(串口,sg90舵机,TFT屏幕移植)-零基础教程
本文介绍了CH32V307单片机的串口3、SG90舵机和LCD屏幕的移植与使用方法。串口3部分详细说明了引脚配置、初始化流程及中断处理,强调要注意总线挂载。SG90舵机部分演示了通过GPIO和PWM两种控制方式,提供了定时器初始化代码和占空比设置方法。LCD屏幕部分包含接线说明、驱动移植步骤、基本显示操作和汉字显示实现,并展示了进度条绘制和图片显示功能。全文提供了完整的代码示例,强调可通过AI辅助
说明:如果大家图库中没有对应照片,可以直接在我的gitee或这github上对我完整的代码进行下载与使用(我的图库文件pic.h)
紧急说明:本文使用的LCD_Show_Chinese这个是我封装的函数,这个函数我会在下一将进行展示
1.串口3的移植与使用
-
先找到串口3所挂载的总线上->然后找另外一个数据手册查询串口3所使用的引脚
CH32FV2x_V3xRM
CH32V307DS0(查引脚)
-
重新创建一个工程(按照上一章的操作)
-
将串口中断和串口初始化还有快速中断cv下来进行项目的开发与使用(大家只需要会修改引脚即可看得懂,大概看得懂代码的意思,知道代码该怎么用就行)-可以使用ai进行辅助开发
串口初始化(进行串口移植时只需要把串口3的名称,挂载总线,引脚初始化进行修改即可)-注意:一定要查看对应的挂载总线APB
void Usart3_Init() { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; USART_Init(USART3, &USART_InitStructure); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_Cmd(USART3, ENABLE); }串口中断
void USART3_IRQHandler(void) { u8 temp; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { temp=USART_ReceiveData(USART3); USART_SendData(USART3, temp+1); } USART_ClearITPendingBit(USART3, USART_IT_RXNE); }串口快速中断(放置在#include<xxx.h>下方)
void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));//定时器3快速中断 -
主函数的书写->编译下载
int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 SystemCoreClockUpdate();//时钟配置 //USART_Printf_Init(115200);//串口1初始化 Delay_Init();//延时函数初始化 Usart3_Init(); GPIO_InitTypeDef GPIO_InitStructure = {0};//定义了一个GPIO的结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开了GPIO外设的时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//GPIO的三种模式 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//将结构体的首地址传入 while(1) { USART_SendData(USART3, 'a'); Delay_Ms(1000); } } -
接线-使用USB-TTL连接板子上的串口3-注意与单片机共地->使用串口助手观察现象(首先查看是否接收到a,然后通过串口助手发送1查看是否回复2)
2.SG90舵机的移植与使用-PWM控制
-
重新建立工程来书写
-
首先将第一讲的LED使用到的PC2引脚初始化cv过来
int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 SystemCoreClockUpdate();//时钟配置 //USART_Printf_Init(115200);//串口1初始化 Delay_Init();//延时函数初始化 GPIO_InitTypeDef GPIO_InitStructure = {0};//定义了一个GPIO的结构体,用来传参 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//打开了GPIO外设的时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//GPIO的三种设置(引脚)-由于我选择连接LED1的引脚为PC2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//GPIO的三种设置(模式)-推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO的三种设置(速度) GPIO_Init(GPIOC, &GPIO_InitStructure);//将结构体的首地址传入 while(1) { } } -
接线说明-PC2与SG90的PWM的那条线相连
-
书写舵机控制代码-验证舵机接线是否有误
while(1) { GPIO_ResetBits(GPIOC, GPIO_Pin_2); Delay_Ms(20); GPIO_SetBits(GPIOC, GPIO_Pin_2); Delay_Us(1500); } -
删去刚刚的引脚初始化
-
定时器控制SG90舵机-可以生成更精确的PWM波(注意这里我使用的PWM引脚是PA0)
定时器初始化以及引脚初始化书写
// 定义舵机的PWM周期和占空比 #define PWM_PERIOD 20000 // PWM周期为20ms (20000us) #define PWM_MIN 500 // 最小脉宽为0.5ms (500us) #define PWM_MAX 2500 // 最大脉宽为2.5ms (2500us) //定时器初始化 // 初始化TIM2以生成PWM信号- void TIM2_PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 配置TIM2的基本参数 TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD - 1; // 设置自动重装值 TIM_TimeBaseStructure.TIM_Prescaler = 96 - 1; // 设置预分频器,96MHz/96 = 1MHz (1us) TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 配置TIM2的PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = PWM_MIN; // 初始占空比为最小值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 配置TIM2通道1 TIM_OC1Init(TIM2, &TIM_OCInitStructure); // 使用TIM2的通道1 TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能TIM2通道1的预装载寄存器 TIM_ARRPreloadConfig(TIM2, ENABLE); // 使能TIM2的自动重装寄存器预装载 TIM_Cmd(TIM2, ENABLE); // 使能TIM2 } //PWM引脚初始化 void GPIO_Pwm_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 GPIO_InitTypeDef GPIO_InitStructure = {0};//定义了一个GPIO的结构体,用来传参 // 配置PA0为复用推挽输出(TIM2通道1) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); } -
主函数的书写
int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 SystemCoreClockUpdate();//时钟配置 //USART_Printf_Init(115200);//串口1初始化 Delay_Init();//延时函数初始化 TIM2_PWM_Init();//定时器初始化 GPIO_Pwm_Init();//GPIO初始化 TIM_SetCompare1(TIM2, 1500);//设置占空比 while(1) { } } -
编译测试
-
舵机转动的封装函数书写
void lock(unsigned char mode)//舵机的工作模式0-上锁 1-开锁 { if(mode==0)//0度 { TIM_SetCompare1(TIM2, 500);//设置占空比 }else if(mode==1) { TIM_SetCompare1(TIM2, 1500);//设置占空比 } }
3.屏幕的移植
-
接线说明(VCC-3.3V SCL-PB3 SDA-PB5 RES-3.3V DC-PD3 CS-PD4 BLK-3.3V GND-记得共地)-推荐这么接线还有一点注意供电稳定
例程位置
其中里面有LCD接线-LCD屏幕实验教程
-
双击打开spi_lcd这个例程,编译运行,发现错误将错误直接注释掉即可,下载测试(查看现象是否是符合预期)
-
创建一个Driver文件夹用于存放移植过来的屏幕驱动(如图所示)

添加方式为:右键点击工程->添加已存在目录->Driver文件夹
-
在Driver文件夹中右键新建.c和.h文件(lcd.c和.h)

-
将例程的lcd.c和.h进行cv到我们自己创建的文件中
-
添加文件路径
右键user文件夹(属性)->C/C++ General->路径和符号->添加->勾选->工作空间->选择Driver文件夹->应用并关闭


-
将例程的#include "font_ascii_16x8.h"这个文件的代码也复制到我们的Driver文件夹中(注意新建这个.h文件)
-
主文件的书写
#include "lcd.h"//头文件定义书写-这个放到上方的头文件定义位置 //中间省略 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 SystemCoreClockUpdate();//时钟配置 //USART_Printf_Init(115200);//串口1初始化 Delay_Init();//延时函数初始化 TIM2_PWM_Init();//定时器初始化 GPIO_Pwm_Init();//GPIO初始化 TIM_SetCompare1(TIM2, 1500);//设置占空比 LCD_Init();//LCD初始化 LCD_Fill(0, 0, 127, 127, WHITE);//先将屏幕清空为白色 LCD_Fill(10,10,20,20,RED);//再显示我们的红色小方块 while(1) { } } -
编译下载
-
屏幕上绘制进度条(这个函数可以放置在屏幕清空后进行)
unsigned char i=0; while(i<128) { LCD_DrawLine(i, 100, i, 127, RED);//绘制一条红色的随时间增长的红线(可以制作为进度条) i++; Delay_Ms(20); } -
模块资料里面的打开文字取模软件(PCtoLCD2002)->点击齿轮->设置如下(注意设置字宽和字高)

-
生成自己想要的字模(在生成字模旁边就是文字输入框)->复制->粘贴至font_ascii_16x8.h文件中汉字字模位置(格式与我上面相同即可)

-
主函数书写(注意我们字的大小是16,所以使用LCD_Show_Chinese这个API需要注意字的大小)
int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 SystemCoreClockUpdate();//时钟配置 //USART_Printf_Init(115200);//串口1初始化 Delay_Init();//延时函数初始化 TIM2_PWM_Init();//定时器初始化 GPIO_Pwm_Init();//GPIO初始化 TIM_SetCompare1(TIM2, 1500);//设置占空比 LCD_Init();//LCD初始化 LCD_Fill(0, 0, 127, 127, WHITE);//先将屏幕清空为白色 unsigned char i=0; while(i<128) { LCD_DrawLine(i, 100, i, 127, RED);//绘制一条红色的随时间增长的红线(可以制作为进度条) i++; Delay_Ms(20); } LCD_Show_Chinese(0, 0, "门锁状态:上锁", RED, WHITE, 16, 0); LCD_Show_Chinese(0,30,"输入密码",RED,WHITE,16,0); while(1) { } } -
大家可以根据自己的想法进行DIY即可(若有不知到的API可以将代码甩给AI进行辅助开发)
-
创建两个文件pic.c和.h并在主文件中进行引用-这个是放置图片取模软件取下来的图
#include "pic.h"//照片头文件 -
这个工程文件的完整代码我放入百度网盘,gitee,github中,可以直接使用我的pic.c和.h代码
-
这是我的LCD主文件操作(其中LCD_ShowPicture的api使用如图所示)
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
SystemCoreClockUpdate();//时钟配置
//USART_Printf_Init(115200);//串口1初始化
Delay_Init();//延时函数初始化
TIM2_PWM_Init();//定时器初始化
GPIO_Pwm_Init();//GPIO初始化
TIM_SetCompare1(TIM2, 1500);//设置占空比
LCD_Init();//LCD初始化
LCD_Fill(0, 0, 127, 127, WHITE);
LCD_ShowPicture(0, 0, 128, 128, gImage_1);
unsigned char i=0;
while(i<128)
{
LCD_DrawLine(i, 0, i, 10, RED);//绘制一条红色的随时间增长的红线(可以制作为进度条)
i++;
Delay_Ms(20);
}
/*进度条走完后,首页显示*/
LCD_ShowPicture(0, 0, 128, 128, gImage_2);
LCD_Show_Chinese(0, 0, "门锁状态:上锁", RED, WHITE, 16, 0);
LCD_Show_Chinese(0,30,"输入密码",RED,WHITE,16,0);
while(1)
{
}
}
更多推荐



所有评论(0)