Cortex M3核学习

本文介绍了Cortex M3核的SysTick定时器配置,包括如何设置计数值、中断优先级,并阐述了SysTick在操作系统中的作用。同时,提到了UART接收的设置,通过示例函数展示了接收状态标记和缓冲区的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验室的MCU项目中主要核心CPU使用的是Cortex M3 ,就此学习嵌入式工作组的头文件以及一些函数学习,作为自己嵌入式学习的入门,持之以恒,目标明年7月找工作之前能够比较熟悉的掌握了解嵌入式开发。

首先main.c一个简单的函数:

int main(void)
{
//  BSP_LED_Init();
//  delay_init();
//  	u8 flag = true;
// 	tim0_cnt = 0;
 	example_uart();
// 	tim_nvic_init(1);	// 定时 1ms

	while(1)
	{
//		OpenLED();
//		delay_ms(1000);
//		CloseLED();
//		delay_ms(1000);
	}
}

可以看到主函数main.c内只有一个example_uart的函数,这是一个uart中断的例程函数。

进入这个可以看见在头文件中声明了以下几组函数:

////////////////////////////////////////////////////////////////////////////////
#ifndef __BSP_UART_H
#define __BSP_UART_H
////////////////////////////////////////////////////////////////////////////////

#include “type.h”

// 定义最大接收字节数 200
#define UART_REC_LEN 200

////////////////////////////////////////////////////////////////////////////////
///

#ifdef BSP_UART_C

#define GLOBAL
#else
#define GLOBAL extern
#endif

// 接收状态标记
GLOBAL u16 UART_RX_STA;
// 接收缓冲,最大 UART_REC_LEN 个字节
GLOBAL u8 UART_RX_BUF[UART_REC_LEN];
GLOBAL char printBuf[100];

#undef GLOBAL

////////////////////////////////////////////////////////////////////////////////

void UartSendByte(u8 dat);
void UartSendGroup(u8* buf,u16 len);
void uart_nvic_init(u32 bound);
void example_uart();

进入example_uart ()函数体:

void example_uart()
{
u8 t, len;
u16 times = 0;
u8 tog;

delay_init();
BSP_LED_Init();

LED0_on();
LED0_off();

/*串口初始化为9600*/
uart_nvic_init(9600);

while(1)
{
    if(UART_RX_STA & 0x8000)
    {
        /*得到此次接收到的数据长度*/
        len = UART_RX_STA & 0x3fff;
        UartSendGroup((u8*)printBuf, sprintf(printBuf,"\r\nYou Send MSG:\r\n"));
        for(t = 0; t < len; t ++)
        {
            while (UART_GetFlagStatus(UART0, UART_FLAG_TXFEMP) == RESET);
            UART_SendData(UART0, (u8)UART_RX_BUF[t]);
        }
        /*插入换行*/
        UartSendGroup((u8*)printBuf, sprintf(printBuf,"\r\n\r\n"));
        UART_RX_STA = 0;
    }else
    {
        times++;
        if(times % 500 == 0)
        {
            UartSendGroup((u8*)printBuf, sprintf(printBuf,"\r\n ULP32 FPGA COM TEST! 串口测试 \r\n"));
        }
        if(times % 200 == 0) UartSendGroup((u8*)printBuf, sprintf(printBuf,"Place Send Data and Enter!\r\n"));
        /*闪烁LED,提示系统正在运行*/
		if(times % 10 == 0)
		{
		  	if(tog == false)
			{
				LED0_on();
				tog = true;
			}
			else
			{
			  	tog = false;
				LED0_off();
			}
		}
        delay_ms(5);
    }
}

}

首先是delay_init()函数:
这是一个Systicks中断函数:
//配置systick中断时间
void delay_init(void)
{
//1 us定时中断
//SysTick_Config(SYSTEM_CLOCK / 1000000);
//1ms 定时中断
SysTick_Config(SYSTEM_CLOCK / 1000);//定时时间计算公式T=ticks*(1/f)=25_000*(1/25000000)=1ms
// SysTick_Config(SysTick_LOAD_RELOAD_Msk);
}

进入配置函数SysTick_Config函数:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)//max SysTick_LOAD_RELOAD_Msk is 0xff_ffff, equal to 16_777_215\判断是否超出范围
{
return (1UL); /* Reload value impossible */
}

SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register /
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /
set Priority for Systick Interrupt /
SysTick->VAL = 0UL; /
Load the SysTick Counter Value /
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /
Enable SysTick IRQ and SysTick Timer /
return (0UL); /
Function successful */
}
这个函数里面包含了SysTick–>Load设置计数值
NVIC_SetPriority设置SysTick中断优先级

__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
//SCB用来处理内核中断,中断号小于0
}
}
这里IRQ为-1,priority=7;因为SysTick中断属于内核中断,中断号小于0;
计算SCB->SHP[11]=15


这里面寄存器很多,在这里大部分我们不用去管,有一个数组SHP[12],一定要看清他是8位数组啊!这个数组是很重要的,他是用来设置内核异常的优先级别,并不是想的在NVIC里设置,那个是大于15号中断的优先组别,换句话就是外部中断什么看门狗,定时器,串口啥的,外设的中断优先级设置在NVIC地IP数组中,而小于这个的都是内部异常,他不归NVIC管制,他受谁管呢?就是这个SHP[12],滴答属于内核的异常所以他要用SHP[12]来设置,和内核手册中讲到的那三个(SHRP1-SHRP3)32位寄存器一一对应,算下来正好有12个字节,最后一个字节就是我要的SYStick的优先级设置,他只用了他的高四位,而第四位保留,所以他的范围是0-15之间的任意数!!


SysTick-Val设置counter值
SysTick->CTRL Enable SysTick IRQ and SysTick Timer Function successful
在这里插入图片描述
在这里插入图片描述
Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

作者:yx_l128125
来源:优快云
原文:https://blog.youkuaiyun.com/yx_l128125/article/details/7884423
版权声明:本文为博主原创文章,转载请附上博文链接!
至此SysTick中断设置完毕

下面设置串口初始化
在这里插入图片描述
在这里插入图片描述
更正:IER[0]先置位,当data_ready被置位后进入接收中断
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值