打印
[MM32硬件]

【EV Board (MM32L0136C7P)测评】玩透基于Systick的多种应用

[复制链接]
504|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lilijin1995 于 2022-12-1 19:39 编辑

各位大佬,大家好,我又来水帖子了,本期给大家带来的是MM32L0136C7P的评估板测试。
哈哈,又是一个玩梗的案子。

2022年11月27日:
基于Systick实现1ms中断
● 开箱晒图:
收到EVB-l0136正是我换了新工作台面的日子,可谓双喜临门!!!
特性介绍:
  • Arm Cortex-M0+ 内核
  • 板载 MM32L0136C7P(LQFP64)
  • 外扩 UART、SPI、Micro-USB 接口
  • 4 x Key、4 x LED
  • 4 x 功能选择开关
  • I2S Speaker
  • 板载段码 LCD 屏

主控芯片介绍:
       MM32L0136 微控制器搭载 Arm ® Cortex ® -M0+ 内核,最高工作频率可达 48MHz。内置
64KB 高速存储器,并集成了丰富的 I/O 端口和外设模块。MM32L0136 包含 1 个 12 位的 ADC、
1 个比较器、2 个 16 位通用定时器、2 个 16 位基本定时器、1 个低功耗定时器和 1 个 RTC
计数器,还包含标准的通信接口:2 个 UART 接口、1 个低功耗 UART 接口、2 个 SPI 接
口、2 个 I2S 接口和 1 个 I2C 接口。此外,MM32L0136 还内置了段码式液晶驱动模块(SLCD)
和红外信号调制模块(IRM)。
MM32L0136 工作电压为 1.8V ∼ 5.5V,工作温度范围(环境温度)为 -40°C ∼ +85°C。内置
多种省电工作模式保证低功耗应用的要求。
这些丰富的外设配置,使得本产品微控制器适合于多种应用场合:
       • 空调遥控器
       • 温控器
       • 耳、额温枪
       • 便携医疗设备
       • 气、水、热表
       • 小家电
MM32L0136 提供 LQFP64 和 LQFP48 封装形式。
● 上电测试:
       收到后,简单了玩了以下,板子可播放音乐因为有I2S Speak,强!!!并且断码屏也有对应的显示。简单看了以下外设例程

另外有其他应用例程
同时有如下组件
例程可如此丰富,满足了绝大部分应用场景。
● 搭建开发环境:
软件安装、驱动安装、例程库资源下载。
SDK 软件请从 https://mindsdk.mindmotion.com.cn 下载,需要注册一下
我习惯于使用MDK开发,而使用MDK需要对应的MCU支持包,这里官网可以下载,并且一步到位,提供了多款MCU的。


● 例程测试:
看了多个例程,而且我发现所有例程竟然没有一个例程是基于systick实现delay的,所以我的第一个想法是自己实现一个delay,但前提又是基于Systick需要有一个准确的时基。所以这里先来实现一个准确的1ms的SysTick_Handler。测试的话就用LED2对应的PB9。
首先我创建了一个MyBSP文件夹和代码分组存放我们自己写的代码,以下是Systick.c

#include "Systick.h"
#include "clock_init.h"
#include "board_init.h"

u8 i = 0;
u32 Counter = 0;

void SysTick_Handler(void)
{
    Counter++;
    if(Counter >= 500) {
        Counter = 0;
                GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, (i == 0) ? (i = 1) : (i = 0)); /* led off. */
    }
}

void Systick_init(void)
{
    if (SysTick_Config(CLOCK_SYSTICK_FREQ)) {
        // Capture error
        while (1);
    }
    // Configure the SysTick handler priority
    NVIC_SetPriority(SysTick_IRQn, 0x0);//SysTickinterrupt priority class set
}




其中GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, (i == 0) ? (i = 1) : (i = 0))是翻转LED2.
SysTick_Config是系统Tick配置初始化系统计时器及其中断,并启动系统计时计时器。CLOCK_SYSTICK_FREQ是两个中断之间的滴答数如下定义
<font face="楷体, 楷体_GB2312">#define CLOCK_SYS_FREQ         48000000u
#define CLOCK_SYSTICK_FREQ     (CLOCK_SYS_FREQ/1000u)</font>
系统时钟是48MHz,Systick=CLOCK_SYS_FREQ/1000  则是配置了1ms中断,即1ms进入SysTick_Handler一次,Counter 自加500次则每500ms翻转一次,也就是说灯闪烁1Hz频率。使用逻辑分析仪测得正是1Hz。



2022年11月28日:
基于Systick实现us与ms延迟
我们上节基于systick实现了1ms中断,我们今天实现两个延迟函数,delayus与delayms。
首先是初始化:
#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
这里SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8是选择系统时钟源8分频,所以CLOCK_SYSTICK_FREQ=CLOCK_SYS_FREQ/8000000,
最后通过我们在main函数中测试一下。

首先是delayus测试,
int main(void)
{
        u8 i = 0;
    BOARD_Init();
        delay_init();

    while (1)
    {

                delay_us(1);
               
                GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, (i == 0) ? (i = 1) : (i = 0)); /* led off. */

    }
}
目的是翻转LED2,测得时序如下:


可以看到us延迟不准确,然后C语言编译之后指令周期肯定不是1us,但总感觉不是那么准了。这里就不深究了。
接着我们测试ms
<font face="楷体, 楷体_GB2312">int main(void)
{
        u8 i = 0;
    BOARD_Init();
        delay_init();

    while (1)
    {

                delay_ms(1);
               
                GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, (i == 0) ? (i = 1) : (i = 0)); /* led off. */

    }
}</font>

测得的时序如下,

ms是准的。

2022年11月30日:

3.3.1简介
MultiTimer 是一个软件定时器扩展模块,可无限扩展你所需的定时器任务,取代传统的标志位判断方式, 更优雅更便捷地管理程序的时间触发时序。
3.3.2使用方法
  • 配置系统时间基准接口,安装定时器驱动;
  • 实例化一个定时器对象;
  • 设置定时时间,超时回调处理函数, 用户上下指针,启动定时器;
  • 在主循环调用定时器后台处理函数

3.3.3功能限制
1.定时器的时钟频率直接影响定时器的精确度,尽可能采用1ms/5ms/10ms这几个精度较高的tick;

2.定时器的回调函数内不应执行耗时操作,否则可能因占用过长的时间,导致其他定时器无法正常超时;

3.由于定时器的回调函数是在 MultiTimerYield 内执行的,需要注意栈空间的使用不能过大,否则可能会导致栈溢出。

3.3.4移植到EV Board (MM32L0136C7P)
第一步是配置好时基函数:

u32 Counter = 0;

void SysTick_Handler(void)
{
    Counter++;

}

uint32_t HAL_GetTick(void)
{
  return Counter;
}


第二步是实例化两个定时器对象,一个用于按键扫描,一个用于控制LED的灯。
MultiTimer timer1;
MultiTimer timer2;
第三步,设置定时时间,超时回调处理函数, 用户上下指针,启动定时器;


static uint8_t keydown=0;

void KeyTimer1Callback(MultiTimer* timer, void *userData)
{
        if(GPIO_ReadInDataBit(GPIOD,GPIO_PIN_5)==0)
        {
                printf("Key0 dowm!\r\n");
                keydown=1;
        }else{
                keydown=0;
                printf("Key0 up!\r\n");
        }
    MultiTimerStart(timer, 10, KeyTimer1Callback, userData);
}

void LEDTimer2Callback(MultiTimer* timer, void *userData)
{
        if(keydown==1)
        {
                GPIO_WriteBit(GPIOB,GPIO_PIN_10,0);
                printf("LED ON!\r\n");
        }else{
                GPIO_WriteBit(GPIOB,GPIO_PIN_10,1);
                printf("LED OFF!\r\n");           
        }
    MultiTimerStart(timer, 10, LEDTimer2Callback, userData);
}



最后,在主循环调用定时器后台处理函数
int main(void)
{
    u8 i = 0;
    BOARD_Init();
    Systick_init();
    MultiTimerInstall(PlatformTicksGetFunc);
    MultiTimerStart(&timer1, 5, KeyTimer1Callback, NULL);
    MultiTimerStart(&timer2, 10, LEDTimer2Callback, NULL);
    while (1)
    {
                MultiTimerYield();
    }
}








使用特权

评论回复
沙发
cemaj| | 2022-12-6 13:24 | 只看该作者
Systick的功能确实强大很多。

使用特权

评论回复
板凳
lihuami| | 2022-12-6 17:26 | 只看该作者
Systick基准时钟的代表              

使用特权

评论回复
地板
yeates333| | 2022-12-6 17:47 | 只看该作者
可以做延时函数的。              

使用特权

评论回复
5
sanfuzi| | 2022-12-12 11:51 | 只看该作者
还是使用定时器比较好一些。              

使用特权

评论回复
6
robertesth| | 2022-12-12 13:41 | 只看该作者
MM32L0136C7P的systick如何作为驱动时钟?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

162

帖子

4

粉丝