1、利用SysTick定时器编写倒计时程序,如初始设置为2分30秒,每秒在屏幕上输出一次时间,倒计时为0后,红灯亮,停止屏幕输出,并关闭SysTick定时器的中断。
#define GLOBLE_VAR
#include "includes.h"
int main(void)
{
uint8_t mSec; // 记当前秒的值
DISABLE_INTERRUPTS;
wdog_stop();
gTime[0] = 0; // 时
gTime[1] = 2; // 分
gTime[2] = 30; // 秒
mSec = gTime[2]; // 记住当前秒的值
gpio_init(LIGHT_RED, GPIO_OUTPUT, LIGHT_OFF); // 初始化红灯暗
systick_init(10); // 设置systick为10ms中断
ENABLE_INTERRUPTS;
printf(" GZHU 32106100165 MYJ \n");
for (;;)
{
if (gTime[2] == mSec)
continue;
mSec = gTime[2];
printf("%d:%d:%d\n", gTime[0], gTime[1], gTime[2]);
if (gTime[0] == 0 && gTime[1] == 0 && gTime[2] == 0)
{
gpio_set(LIGHT_RED, LIGHT_ON); // 设置灯“亮”
systick_close();
printf("红灯亮!");
break;
}
}
}
#include "includes.h"
void SecSub1(uint8_t *p);
void SysTick_Handler()
{
static uint8_t SysTickCount = 0;
SysTickCount++; // Tick单元+1
wdog_feed(); // 看门狗“喂狗”
if (SysTickCount >= 100)
{
SysTickCount = 0;
SecSub1(gTime);
}
}
void SecSub1(uint8_t *p)
{
*(p + 2) -= 1; // 秒-1
if (*(p + 2) <= 0)
{
if (*(p + 1) <= 0)
{ // 计时结束
return;
}
*(p + 2) = 60; // 重置为60秒
*(p + 1) -= 1; // 分-1
if (*(p + 1) <= 0)
{
if (*p <= 0)
{
return;
}
*(p + 1) = 60; // 清分
*p -= 1; // 时-1
if (*p <= 24)
{
return;
}
}
}
}
![](https://img-blog.csdnimg.cn/direct/1c01e95333d54297869eb144047a211e.png)
![](https://img-blog.csdnimg.cn/direct/76dd8fe51a524045899ae9578d3aef57.png)
![](https://img-blog.csdnimg.cn/direct/cc96e467a51b4252b81f7588234b1b3b.png)
2、利用RTC显示日期(年月日、时分秒),每秒更新。并设置某个时间的闹钟。闹钟时间到时,屏幕上显示有你的姓名的文字,并点亮绿灯。
#define GLOBLE_VAR
#include "includes.h"
int main(void)
{
uint32_t mMainLoopCount; // 主循环次数变量
DISABLE_INTERRUPTS;
mMainLoopCount = 0; // 主循环次数变量
g_RTC_Flag = 0;
gpio_init(LIGHT_GREEN, GPIO_OUTPUT, LIGHT_OFF); // 初始化蓝灯
uart_init(UART_User, 115200);
RTC_Init(); // RTC初始化
RTC_Set_Time(13, 11, 13); // 设置时间为0:0:0
RTC_Set_Date(1, 1, 1, 1); // 设置日期
RTC_PeriodWKUP_Enable_Int(); // 使能唤醒中断
uart_enable_re_int(UART_User); // 使能接收中断
RTC_Alarm_Enable_Int(0); // 使能闹钟中断
ENABLE_INTERRUPTS;
RTC_Set_PeriodWakeUp(1); // 配置WAKE UP中断,每秒中断一次
RTC_Set_Alarm(0, 1, 13, 11, 53); // 配置闹钟时间
printf(" GZHU 32106100165 MYJ \n");
for (;;)
{
mMainLoopCount++;
if (mMainLoopCount <= 12888999)
continue;
mMainLoopCount = 0;
if (g_RTC_Flag == 1) // 根据串口接收的数据设置基准时间
{
g_RTC_Flag = 0;
gcRTC_Date_Time.Year = (uint8_t)((gcRTCBuf[1] - '0') * 10 + (gcRTCBuf[2] - '0'));
gcRTC_Date_Time.Month = (uint8_t)((gcRTCBuf[4] - '0') * 10 + (gcRTCBuf[5] - '0'));
gcRTC_Date_Time.Date = (uint8_t)((gcRTCBuf[7] - '0') * 10 + (gcRTCBuf[8] - '0'));
gcRTC_Date_Time.Hours = (uint8_t)((gcRTCBuf[10] - '0') * 10 + (gcRTCBuf[11] - '0'));
gcRTC_Date_Time.Minutes = (uint8_t)((gcRTCBuf[13] - '0') * 10 + (gcRTCBuf[14] - '0'));
gcRTC_Date_Time.Seconds = (uint8_t)((gcRTCBuf[16] - '0') * 10 + (gcRTCBuf[17] - '0'));
gcRTC_Date_Time.Weekday = (uint8_t)((gcRTCBuf[23] - '0'));
RTC_Set_Time(gcRTC_Date_Time.Hours, gcRTC_Date_Time.Minutes, gcRTC_Date_Time.Seconds); // 设置时间
RTC_Set_Date(gcRTC_Date_Time.Year, gcRTC_Date_Time.Month, gcRTC_Date_Time.Date, gcRTC_Date_Time.Weekday); // 设置日期
}
}
}
![](https://img-blog.csdnimg.cn/direct/9034a313bff4451982fb4193497d9fa0.png)
![](https://img-blog.csdnimg.cn/direct/d86cf0cda821496a921e9c48896d8db8.png)
3、利用PWM脉宽调制,交替显示红灯的5个短闪和5个长闪。
#define GLOBLE_VAR
#include "includes.h"
int main(void)
{
uint8_t mFlag; //灯的状态标志
uint8_t Flag; //希望采集的电平高低标志
double m_duty; //占空比
uint32_t m_i; //控制在未知周期内不同占空比的波形只打印有限次
uint8_t m_K; //确保每次能正确打印输出PWM波形
DISABLE_INTERRUPTS;
Flag=1;
mFlag=0; //灯的状态标志
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化红灯暗
pwm_init(PWM_USER,1500,1000,10.0,PWM_CENTER,PWM_MINUS); //PWM输出初始化
ENABLE_INTERRUPTS;
printf(" GZHU 32106100165 MYJ\n");
m_K=0;
m_duty=10.0; //占空比设置为10%
for(;;)
{
pwm_update(PWM_USER,m_duty); //调节占空比
for (m_i=0;m_i<10;m_i++) //m_i<10为了控制小灯闪烁5次
{
m_K=0; //保证每次输出打印完整的PWM波,再进入下一个循环
do
{
mFlag=gpio_get(PWM_USER); //获取灯的状态标志
if ((mFlag==1)&&(Flag==1))
{
printf("高电平:1\n");
Flag=0;
m_K++;
gpio_reverse(LIGHT_RED);//小灯反转
}
else if ((mFlag==0)&&(Flag==0))
{
printf("低电平:0\n");
Flag=1;
m_K++;
gpio_reverse(LIGHT_RED);
}
}
while (m_K<1);
}
m_duty = 100.0-m_duty; //不断循环每5次灯闪烁调节占空比
}
}
![](https://img-blog.csdnimg.cn/direct/8fefb966a62b4d13b0c3246244588038.png)
![](https://img-blog.csdnimg.cn/direct/640203bf532a404da8200fce1e2a3a3b.png)
![](https://img-blog.csdnimg.cn/direct/06fdcebd08c443a9bf11b3f50738735d.png)
4、GEC39定义为输出引脚,GEC10定义为输入引脚,用杜邦线将两个引脚相连,验证捕捉实验程序Incapture-Outcmp-20211110,观察输出的时间间隔。
#define GLOBLE_VAR
#include "includes.h"
void Delay_ms(uint16_t u16ms);
int main(void)
{
uint8_t mFlag; // 灯的状态标志
uint8_t flag; // 标记高低电平
DISABLE_INTERRUPTS;
mFlag = 'A'; // 灯的状态标志
gTime[0] = 0; // 分钟
gTime[1] = 0; // 秒
gTime[2] = 0; // 毫秒
period = 1000; // 自动重装载寄存器初始值
gpio_init(LIGHT_BLUE, GPIO_OUTPUT, LIGHT_ON); // 初始化蓝灯
outcmp_init(OUTCMP_USER, 3000, 200, 50.0, CMP_REV); // 输出比较初始化
incapture_init(INCAP_USER, 375, 1000, CAP_DOUBLE); // 上升沿捕捉初始化
systick_init(1); // 设置systick为1ms中断
cap_enable_int(INCAP_USER); // 使能输入捕捉中断
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
printf("金葫芦提示: \n");
printf(" (1)蓝灯每秒闪烁一次,作为运行指示\n");
printf(" (2)设置GEC39为输出比较引脚,\n");
printf(" 设置GEC10为输入捕捉引脚,沿跳变捕捉\n");
printf(" (3)用导线将GEC39与GEC10连接 \n");
printf(" (4)程序使得输出比较引脚输出高低电平,输入捕捉引脚捕捉\n");
printf(" 后用printf输出,PC机程序据此显示波形引脚捕捉\n");
printf("-----GZHU 32106100165 MYJ-----\n");
for (;;) // for(;;)(开头)
{
flag = gpio_get(INCAP_USER);
// 灯状态标志mFlag为'L',改变灯状态及标志
if (mFlag == 'L' && flag == 1) // 判断灯的状态标志
{
mFlag = 'A'; // 灯的状态标志
gpio_set(LIGHT_BLUE, LIGHT_ON); // 灯“亮”
}
// 如灯状态标志mFlag为'A',改变灯状态及标志
else if (mFlag == 'A' && flag == 0) // 判断灯的状态标志
{
mFlag = 'L'; // 灯的状态标志
gpio_set(LIGHT_BLUE, LIGHT_OFF); // 灯“暗”
}
} // for(;;)结尾
}
void Delay_ms(uint16_t u16ms)
{
uint32_t u32ctr;
for (u32ctr = 0; u32ctr < 8000 * u16ms; u32ctr++)
{
__ASM("NOP");
}
}
![](https://img-blog.csdnimg.cn/direct/f1e12101bcd3425194ebcd96788d3c92.png)
![](https://img-blog.csdnimg.cn/direct/e7ed2bc8c05b4ac09d4df4143da57f8a.png)
![](https://img-blog.csdnimg.cn/direct/5f3c8200932244929eda18382f55bc20.png)