《ARM微控制器与嵌入式系统》慕课---实验三 Systick实验

任务一:使用Systick触发LED灯闪烁,间隔时间为1秒

分析:前面已经做过了LED灯闪烁实验,现在只需将delay()改由systick来实现闪烁间隔

1、配置Systick相关寄存器,使其每0.5秒产生一个中断

2、由于要求每1秒切换LED灯闪烁状态,所以需要有一个变量来计数

3、在Systick_Handler()中断服务函数中,更新这个变量值

注意:Systick是一个24bit的定时器,不要超过其范围哦

实现代码如下:

#include "derivative.h" /* include peripheral declarations */

#define BIT(x) (1 << x)

static int times = 0;

void led4_init(void)
{
	SIM_SCGC5 |= BIT(11);  //enable portc clk gating
	
	PORTC_PCR3 |= BIT(8); //config GPIO
	PORTC_PCR4 |= BIT(8); //config GPIO
	PORTC_PCR5 |= BIT(8); //config GPIO
	
	GPIOC_PDDR |= (BIT(3)|BIT(4)|BIT(5)); //direction as output
	
	GPIOC_PDOR |= BIT(4); //green
}

void systick_init(void)
{
	SYST_RVR = 10485000; //0.5s
	SYST_CVR = 0;
	SYST_CSR |= BIT(0) | BIT(1) | BIT(2); 
}
void SysTick_Handler(void)
{
	int i;
	if(times % 2 == 0)
		GPIOC_PTOR |= BIT(4);
	times++;
	i = SYST_CSR;
}

void __enable_irq(void)
{
	asm("CPSIE i");
}

int main(void)
{
	systick_init();
	led4_init();
	__enable_irq();
	
	while(1);
	
	return 0;
}

任务二:在任务一基础上,实现通过DOWN按键来改变闪烁间隔(1HZ and 2HZ)

分析:首先需要配置按键中断,定义一个变量记录当前闪烁间隔,然后在按键中断服务函数中改变该变量值,再将该变量用于Systick中断服务函数判断即可

1、配置与使能S2中断

2、定义变量freq记录闪烁间隔,默认freq = 1,然后在按键中断服务函数PORTCD_IRQHandler()中改变freq值

3、在Systick中断服务函数SysTick_Handler()中,使用times % (freq * 2) == 0来判断是否需要反转GPIO输出值

实现代码如下:

#include "derivative.h" /* include peripheral declarations */

#define BIT(x) (1 << x)

static int times = 0;
static int freq = 1;

void led4_init(void)
{
	SIM_SCGC5 |= BIT(11);  //enable portc clk gating
	
	PORTC_PCR3 |= BIT(8); //config GPIO
	PORTC_PCR4 |= BIT(8); //config GPIO
	PORTC_PCR5 |= BIT(8); //config GPIO
	
	GPIOC_PDDR |= (BIT(3)|BIT(4)|BIT(5)); //direction as output
	
	GPIOC_PDOR |= BIT(4);
}

void s2_init(void)
{
	SIM_SCGC5 |= BIT(11);  //enable portc clk gating
	
	PORTC_PCR7 |= (BIT(8)|BIT(1)|BIT(0)); //config GPIO
	PORTC_PCR7 |= (0xa << 16); //falling edge
	
	GPIOC_PDDR &= ~BIT(7); //direction as input
}

void systick_init(void)
{
	SYST_RVR = 10485000; //0.5s
	SYST_CVR = 0;
	SYST_CSR |= BIT(0) | BIT(1) | BIT(2); 
}

void PORTCD_IRQHandler(void)
{
	if(freq == 1)
		freq = 2;
	else
		freq = 1;

	PORTC_PCR7 |= BIT(24);
}

void SysTick_Handler(void)
{
	int i;
	if(times % (freq * 2) == 0)
		GPIOC_PTOR |= BIT(4);
	times++;
	i = SYST_CSR;
}

void __enable_irq(void)
{
	asm("CPSIE i");
}

void __enable_portc_irq(void)
{
	NVIC_ISER |= BIT(31);
}

int main(void)
{
	systick_init();
	led4_init();
	s2_init();
	__enable_portc_irq();
	__enable_irq();
	
	while(1);
	
	return 0;
}

任务三:使用systick实现一个计时器,并将计时时间通过串口发送给PC

分析:分别定义hour,min,sec三个变量,每当第二次systick产生中断,sec加1,当sec达到60时,min加1,sec归零,当min达到60时,hour加1,min归零,然后将hour,min,sec转换成对应显示字符,最后通过串口发送给PC

实现代码如下:

#include "derivative.h" /* include peripheral declarations */

#define BIT(x) (1 << x)

static int times = 0;

static int sec = 0;
static int min = 0;
static int hour = 0;

void systick_init(void)
{
	SYST_RVR = 10485000; //0.5s
	SYST_CVR = 0;
	SYST_CSR |= BIT(0) | BIT(1) | BIT(2); 
}

void uart1_init(void)
{
	SIM_SCGC5 |= (1 << 13);
	SIM_SCGC4 |= (1 << 11);
	
	PORTE_PCR0 |= (3 << 8);
	PORTE_PCR1 |= (3 << 8);
	
	UART1_C2 |= ((1 << 7)|(1 << 3)|(1 << 2));//enable tx and rx
	
	UART1_BDL |= 0x44; //9600
}

unsigned char num2char(unsigned char n)
{
	if(n >= 0 && n <= 9)
		return n + '0';
	else if(n >= 10 && n <= 15)
		return n - 10 + 'A';
	else
		return 0;
}

void send_char(char c)
{
	while(!(UART1_S1 & BIT(7)));
	UART1_D = c;
	
}

void send_time(int hour,int min, int sec)
{
	send_char(num2char(hour / 10));
	send_char(num2char(hour % 10));
	send_char(' ');
	send_char(':');
	send_char(' ');
	send_char(num2char(min / 10));
	send_char(num2char(min % 10));
	send_char(' ');
	send_char(':');
	send_char(' ');
	send_char(num2char(sec / 10));
	send_char(num2char(sec % 10));
	send_char('\n');
}

void SysTick_Handler(void)
{
	int i;
	if((times % 2) == 0)
	{
		sec++;
		if(sec >= 60)
		{
			min++;
			sec = 0;
		}
		if(min >= 60)
		{
			hour++;
			min = 0;
		}
		if(hour >= 24)
		{
			hour = 0;
		}
		send_time(hour,min,sec);
	}
	times++;
	i = SYST_CSR;
}

void __enable_irq(void)
{
	asm("CPSIE i");
}

int main(void)
{
	systick_init();
	uart1_init();
	__enable_irq();

	while(1);
	
	return 0;
}

至此,实验就玩完了,呵呵,是不是也没有想象中得那么难?相信自己,继续加油哦

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值