【RISC-V MCU CH32V103测评】 ---前进的维子---GPIO和TIMER
[复制链接]
【RISC-V MCU CH32V103测评】 ---前进的维子---GPIO和TIMER
前进的维子
2021年1月22日
前言:
本文介绍CH32V103的GPIO和timer的操作原理。主要参考的是官方的手册。最终做一个呼吸灯的点灯实例。这个例子只是用来“玩”的,只是逻辑讲解一下。实际工作中不要这样使用。
本文,将以工程笔记的方式按步骤记录过程。 通过本文,新手可以学习到,中断式编程的思想。
第一步:明确设计目标
目标:使用定时器和GPIO实现一个“忽明忽暗”的呼吸灯。特点是:灯由亮缓缓的变暗,再由暗缓缓的变亮。由全灭到全亮1秒,由全亮到全灭1秒。
第二步:分析用到的内部外设
内部外设需要用到:定时器、 控制灯的GPIO。选择普通定时器3作为定时器。灯的GPIO还是使用原来的PA0。
第三步:具体的设计方案
实现呼吸灯的功能有很多种办法。我们考虑到,测试程序必须短,为了逻辑简单起见,在这里我们使用定时器周期中断,在定时器中断的中断处理函数中,控制灯GPIO口的亮和灭。再具体一些:我们用一个定时器每1ms中10下(每秒有10000个中断)。渐渐亮的时候,我们一点点的将点亮灯的时间有0.1ms/10ms增加到 10ms/10ms。渐渐熄灭的时候,我们一点点的将灯的熄灭的时间由0ms/10ms增加到10ms/10ms。也就是我们以0.01s(10ms)为一个视觉周期,亮的1秒钟100个亮度等级,灭的1秒钟有100个亮度等级。序列是这样的,开始灯灭(初始化);---->亮0.1ms灭9.9ms--->亮0.2ms灭9.8ms--->…… 亮9.8ms灭0.2ms--->亮9.9ms灭0.1ms---->亮10.0ms-当逐渐暗的时候:亮9.9ms灭0.1ms--->亮9.8ms灭0.2ms--->亮9.7ms灭0.3ms ……亮0.3ms灭9.7ms--->亮0.2ms灭9.8ms --->亮0.1ms灭9.9ms--->灭10.0ms。
注意,这个练习里,我们设计的一切都是为了简单。实际工作中不允许这样做!
这样我们抽象出一些东西:5个变量,
变量1,变量表示当前是逐渐点亮还是逐渐熄灭
变量2,表示下个10.0ms内应该亮的个数
变量3,表示下个10.0ms内应该亮的个数
变量4,表示当前10.0ms内剩余应该亮的个数
变量5,表示当前10.0ms内剩余应该灭的个数
第四步:阅读读手册中与内部外设相关部分
4.1:看GPIO手册
先浏览整个GPIO部分的手册。手册编写的没什么废话。GPIO部分的基本功能包括:GPIO、外部中断、复用、锁定、输入输出配置、模拟输入配置……。我们只用了GPIO部分。
现在都用库函数编程,所以可不看手册中的寄存器页。但是处于对芯片的了解,这里还是看一看,那我们只看PA0口相关的寄存器。GPIO寄存器包括:端口配置寄存器低位和高位;输入数据寄存器;输出数据寄存器;置位复位寄存器;复位寄存器;锁定寄存器;浏览的时候,只要知道是干啥用的,还有是怎么操作的就行。其他可以忽略。
4.2:看定时器3的手册
看的方法是,先浏览一遍手册,然后着重看一下找到自己需要的内容。因为这个习作,所以也不要太仔细的看,大概了解一下就可以了。最后,我们简单的浏览一下寄存器就可以了。我们明确一下:看手册的目的是,1,简单了解外设的功能。2:在使用库编程的时候,我们知道库到底干了什么。对那些名字就不陌生了。
4.3:看中断手册
浏览就好。就是第九章。
第五步:编制代码
有了上面的功能分析还有内部外设手册的阅读我们编代码的时候简单很多了。多的不说了,直接上关键代码。这是在定时器中断处理中调用的函数。 我都用的全局变量。
void timer3_breath_fun(void)
{
if ((m == 0) && (n == 0))//亮和灭都执行完了 开始新周期 重新计算m和n值
{
if (lighting) //如果当前是逐渐亮的过程
{
i = i + 1;//亮的阶数累加
if (i > 100)//大于100表示亮到顶了 该熄灭了
{
lighting = 0x00;//熄灭标记
i = 100;
}
}
else//否则当前是逐渐熄灭的过程
{
if(i==0)//没亮了
{
lighting = 0x01;
i = 0;
}
else
{
i = i - 1;
}
}
j = 100 - i;
m = i;//分配m值
n = j;//分配n值
}
else
{
if(m){
LED_on();
m--;
}
else if (n){
LED_off();
n--;
}
}
}
定时器中断的函数
extern void timer3_breath_fun(void);
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
timer3_breath_fun();
}
}
主函数代码:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
gpio_led_init();//LED灯的IO口初始化
printf("SystemClk:%d\r\n",SystemCoreClock);
printf("This is breath led example not in realy work \r\n");
timer3_init();
while(1);
}
第六步:调试观察效果
直接上图:
后记:
1:维子已经习惯于在VSCode里编代码了,这个IDE对外部的编辑器似乎不是很友好,用VSCode编完保存了,在编译器里不支持更新,甚至连提示都不提示。只能断开再重新打开才好。
2:ch32v103的芯片手册还是很好读的。有单片机基础的朋友会很容易读。虽然库函数已经屏蔽了很多寄存器操作。但是我们还是应该仔细看手册。
2:本篇只是习作。在实际工作中,实现呼吸灯也不是用的这个方法。维子自打出了HAL库开始,很久没用过std库编程了。
下面是附件pdf中 代码的样子,而正文中复制过来的代码光秃秃的。
|