ABOV M0系列开发:M0S11系列_时钟系统与复位管理

时钟系统与复位管理

时钟系统概述

时钟系统是单片机(MCU)正常运行的基础,它决定了系统的运行速度和功耗。ABOV M0S11系列单片机提供了多种时钟源和时钟配置方式,以满足不同应用场景的需求。本节将详细介绍ABOV M0S11系列单片机的时钟系统,包括时钟源、时钟配置和时钟分频等内容。
在这里插入图片描述

时钟源

ABOV M0S11系列单片机支持多种时钟源,包括内部时钟源和外部时钟源。以下是一些主要的时钟源:

  1. 内部高速RC振荡器(HIRC):提供一个高精度的内部时钟源,频率为16MHz。
  2. 内部低速RC振荡器(LIRC):提供一个低功耗的内部时钟源,频率为32.768kHz。
  3. 外部高速晶振(HXT):通过外部晶振提供一个高精度的时钟源,频率范围为4MHz至24MHz。
  4. 外部低速晶振(LXT):通过外部晶振提供一个低功耗的时钟源,频率为32.768kHz。

时钟树

时钟树是单片机时钟系统的重要组成部分,它将不同的时钟源通过时钟分频器和选择器组合起来,为不同的外设和系统提供所需的时钟频率。ABOV M0S11系列单片机的时钟树如下图所示:

        +----------------+
        |  HIRC (16MHz)  |
        +----------------+
                 |
                 v
        +----------------+
        |  HXT (4-24MHz) |
        +----------------+
                 |
                 v
        +----------------+
        |  PLL (可选)    |
        +----------------+
                 |
                 v
        +----------------+
        |  系统时钟源    |
        +----------------+
        /       |       \
       /        |        \
      v         v         v
+--------+ +--------+ +--------+
|  CPU   | |  APB   | |  AHB   |
+--------+ +--------+ +--------+

时钟配置

时钟配置是通过配置寄存器来选择和设置时钟源和分频比。以下是一些主要的时钟配置寄存器:

  • CLKSEL寄存器:用于选择系统时钟源。
  • CLKDIV寄存器:用于设置时钟分频比。
  • PLLCON寄存器:用于配置PLL(锁相环)。

示例代码:配置系统时钟源

以下是一个示例代码,展示如何配置ABOV M0S11系列单片机的系统时钟源为外部高速晶振(HXT)。

#include "abov_m0s11.h"

// 配置系统时钟源为HXT
void configure_system_clock(void) {
    // 使能HXT
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;  // 使能12MHz外部高速晶振

    // 等待HXT稳定
    while (!(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk));

    // 选择HXT作为系统时钟源
    CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | CLK_CLKSEL0_HCLKSEL_HXT;
}

int main(void) {
    // 配置系统时钟
    configure_system_clock();

    // 主程序
    while (1) {
        // 应用代码
    }
}

时钟分频

时钟分频是通过时钟分频器将时钟源的频率分成不同的频率,以满足不同外设的需求。ABOV M0S11系列单片机提供了多个时钟分频器,包括AHB分频器、APB分频器等。

AHB分频器

AHB分频器用于配置CPU和其他高速外设的时钟频率。分频比可以通过CLKDIV寄存器的HCLKDIV位域进行设置。

APB分频器

APB分频器用于配置低速外设的时钟频率。分频比可以通过CLKDIV寄存器的PCLKDIV位域进行设置。

示例代码:配置时钟分频

以下是一个示例代码,展示如何配置AHB分频器和APB分频器。

#include "abov_m0s11.h"

// 配置AHB和APB分频器
void configure_clock_dividers(void) {
    // 配置AHB分频器,分频比为1
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | CLK_CLKDIV_HCLKDIV(1);

    // 配置APB分频器,分频比为2
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_PCLKDIV_Msk) | CLK_CLKDIV_PCLKDIV(2);
}

int main(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 主程序
    while (1) {
        // 应用代码
    }
}

复位管理

复位管理是单片机系统中的重要功能,它确保系统在启动时或异常情况下能够正确地初始化。ABOV M0S11系列单片机提供了多种复位源和复位配置方式,以确保系统的稳定性和可靠性。

复位源

ABOV M0S11系列单片机支持以下复位源:

  1. 上电复位(POR):当单片机上电时自动复位。
  2. 掉电复位(PDR):当单片机掉电时自动复位。
  3. 外部复位(EXR):通过外部复位引脚(RST)触发复位。
  4. 软件复位(SWR):通过软件指令触发复位。
  5. 看门狗复位(WDR):当看门狗定时器超时后触发复位。
  6. 低电压检测复位(LVR):当电源电压低于设定阈值时触发复位。

复位配置

复位配置是通过配置寄存器来选择和设置复位源。以下是一些主要的复位配置寄存器:

  • RSTCON寄存器:用于配置复位源和复位行为。
  • LVDCON寄存器:用于配置低电压检测复位的阈值。

示例代码:配置低电压检测复位

以下是一个示例代码,展示如何配置低电压检测复位(LVR)。

#include "abov_m0s11.h"

// 配置低电压检测复位
void configure_low_voltage_reset(void) {
    // 选择LVR阈值为2.7V
    SYS->LVDCON = (SYS->LVDCON & ~SYS_LVDCON_LVD_VLSEL_Msk) | SYS_LVDCON_LVD_VLSEL_2_7V;

    // 使能LVR
    SYS->LVDCON |= SYS_LVDCON_LVR_EN_Msk;
}

int main(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 配置低电压检测复位
    configure_low_voltage_reset();

    // 主程序
    while (1) {
        // 应用代码
    }
}

示例代码:软件复位

以下是一个示例代码,展示如何通过软件触发系统复位。

#include "abov_m0s11.h"

// 触发软件复位
void trigger_software_reset(void) {
    // 设置软件复位标志
    SYS->RSTCON |= SYS_RSTCON_RSTKEY_Msk | SYS_RSTCON_PORST_Msk;
}

int main(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 配置低电压检测复位
    configure_low_voltage_reset();

    // 触发软件复位
    trigger_software_reset();

    // 主程序
    while (1) {
        // 应用代码
    }
}

复位状态寄存器

复位状态寄存器用于记录复位的来源和状态,以便在系统启动后进行诊断和处理。以下是一些主要的复位状态寄存器位域:

  • RSTSRC寄存器:记录复位来源。
    • PORST_IF:上电复位标志
    • PDRST_IF:掉电复位标志
    • EXTRST_IF:外部复位标志
    • SWRST_IF:软件复位标志
    • WDRST_IF:看门狗复位标志
    • LVRST_IF:低电压检测复位标志

示例代码:读取复位状态

以下是一个示例代码,展示如何读取复位状态寄存器并判断复位来源。

#include "abov_m0s11.h"

// 读取复位状态寄存器
void read_reset_status(void) {
    // 读取复位状态寄存器
    uint32_t reset_status = SYS->RSTSRC;

    // 判断复位来源
    if (reset_status & SYS_RSTSRC_PORST_IF_Msk) {
        printf("上电复位\n");
    }
    if (reset_status & SYS_RSTSRC_PDRST_IF_Msk) {
        printf("掉电复位\n");
    }
    if (reset_status & SYS_RSTSRC_EXTRST_IF_Msk) {
        printf("外部复位\n");
    }
    if (reset_status & SYS_RSTSRC_SWRST_IF_Msk) {
        printf("软件复位\n");
    }
    if (reset_status & SYS_RSTSRC_WDRST_IF_Msk) {
        printf("看门狗复位\n");
    }
    if (reset_status & SYS_RSTSRC_LVRST_IF_Msk) {
        printf("低电压检测复位\n");
    }

    // 清除复位标志
    SYS->RSTSRC = reset_status;
}

int main(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 配置低电压检测复位
    configure_low_voltage_reset();

    // 读取复位状态
    read_reset_status();

    // 主程序
    while (1) {
        // 应用代码
    }
}

复位处理

在复位后,单片机需要进行一系列的初始化操作,以确保系统能够正常运行。这些初始化操作通常包括:

  1. 系统时钟配置:设置系统的时钟源和分频比。
  2. 外设初始化:初始化GPIO、定时器、ADC等外设。
  3. 中断配置:配置中断控制器和中断向量表。
  4. 主程序入口:跳转到主程序的入口点。

示例代码:复位处理函数

以下是一个示例代码,展示如何在复位后进行系统初始化。

#include "abov_m0s11.h"

// 配置系统时钟
void configure_system_clock(void) {
    // 使能HXT
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;  // 使能12MHz外部高速晶振

    // 等待HXT稳定
    while (!(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk));

    // 选择HXT作为系统时钟源
    CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | CLK_CLKSEL0_HCLKSEL_HXT;
}

// 配置时钟分频
void configure_clock_dividers(void) {
    // 配置AHB分频器,分频比为1
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | CLK_CLKDIV_HCLKDIV(1);

    // 配置APB分频器,分频比为2
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_PCLKDIV_Msk) | CLK_CLKDIV_PCLKDIV(2);
}

// 配置低电压检测复位
void configure_low_voltage_reset(void) {
    // 选择LVR阈值为2.7V
    SYS->LVDCON = (SYS->LVDCON & ~SYS_LVDCON_LVD_VLSEL_Msk) | SYS_LVDCON_LVD_VLSEL_2_7V;

    // 使能LVR
    SYS->LVDCON |= SYS_LVDCON_LVR_EN_Msk;
}

// 读取复位状态寄存器
void read_reset_status(void) {
    // 读取复位状态寄存器
    uint32_t reset_status = SYS->RSTSRC;

    // 判断复位来源
    if (reset_status & SYS_RSTSRC_PORST_IF_Msk) {
        printf("上电复位\n");
    }
    if (reset_status & SYS_RSTSRC_PDRST_IF_Msk) {
        printf("掉电复位\n");
    }
    if (reset_status & SYS_RSTSRC_EXTRST_IF_Msk) {
        printf("外部复位\n");
    }
    if (reset_status & SYS_RSTSRC_SWRST_IF_Msk) {
        printf("软件复位\n");
    }
    if (reset_status & SYS_RSTSRC_WDRST_IF_Msk) {
        printf("看门狗复位\n");
    }
    if (reset_status & SYS_RSTSRC_LVRST_IF_Msk) {
        printf("低电压检测复位\n");
    }

    // 清除复位标志
    SYS->RSTSRC = reset_status;
}

// 复位处理函数
void reset_handler(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 配置低电压检测复位
    configure_low_voltage_reset();

    // 初始化GPIO
    GPIO->MODE = (GPIO->MODE & ~GPIO_MODE_MODE0_Msk) | GPIO_MODE_MODE0_INPUT;

    // 初始化定时器
    TIMER->TCSR0 = (TIMER->TCSR0 & ~TIMER_TCSR0_PSC_Msk) | TIMER_TCSR0_PSC(127);  // 设置预分频器
    TIMER->TCSR0 |= TIMER_TCSR0_EN_Msk;  // 使能定时器

    // 初始化中断控制器
    NVIC_EnableIRQ(TIMER0_IRQn);  // 使能定时器0中断

    // 读取复位状态
    read_reset_status();
}

// 定时器0中断处理函数
void TIMER0_IRQHandler(void) {
    // 清除定时器0中断标志
    TIMER->TCSR0 |= TIMER_TCSR0_IF_Msk;

    // 处理定时器0中断
    printf("定时器0中断\n");
}

// 复位向量表
__attribute__((section(".isr_vector"))) const uint32_t isr_vector[] = {
    (uint32_t)&__stack_end__,  // 堆栈指针
    (uint32_t)&reset_handler,  // 复位处理函数
    (uint32_t)&NMI_Handler,    // NMI中断处理函数
    (uint32_t)&HardFault_Handler,  // 硬故障中断处理函数
    (uint32_t)&MemManage_Handler,  // 内存管理中断处理函数
    (uint32_t)&BusFault_Handler,   // 总线故障中断处理函数
    (uint32_t)&UsageFault_Handler,  // 使用故障中断处理函数
    0, 0, 0, 0,  // 保留
    0, 0, 0, 0,  // 保留
    (uint32_t)&SVCall_Handler,  // 系统调用中断处理函数
    (uint32_t)&DebugMon_Handler,  // 调试监控中断处理函数
    0,  // 保留
    (uint32_t)&PendSV_Handler,  // 挂起服务中断处理函数
    (uint32_t)&SysTick_Handler,  // 系统节拍定时器中断处理函数
    (uint32_t)&TIMER0_IRQHandler,  // 定时器0中断处理函数
    // 其他中断处理函数
};

// 缺省中断处理函数
void NMI_Handler(void) __attribute__((weak, alias("default_handler")));
void HardFault_Handler(void) __attribute__((weak, alias("default_handler")));
void MemManage_Handler(void) __attribute__((weak, alias("default_handler")));
void BusFault_Handler(void) __attribute__((weak, alias("default_handler")));
void UsageFault_Handler(void) __attribute__((weak, alias("default_handler")));
void SVCall_Handler(void) __attribute__((weak, alias("default_handler")));
void DebugMon_Handler(void) __attribute__((weak, alias("default_handler")));
void PendSV_Handler(void) __attribute__((weak, alias("default_handler")));
void SysTick_Handler(void) __attribute__((weak, alias("default_handler")));

// 缺省中断处理函数
void default_handler(void) {
    while (1) {
        // 处理缺省中断
    }
}

int main(void) {
    // 跳转到复位处理函数
    reset_handler();

    // 主程序
    while (1) {
        // 应用代码
    }
}

复位后的系统初始化

在复位后,单片机需要进行一系列的初始化操作,以确保系统能够正常运行。这些初始化操作通常包括:

  1. 系统时钟配置:设置系统的时钟源和分频比。
  2. 外设初始化:初始化GPIO、定时器、ADC等外设。
  3. 中断配置:配置中断控制器和中断向量表。
  4. 主程序入口:跳转到主程序的入口点。

示例代码:复位后的系统初始化

以下是一个示例代码,展示如何在复位后进行系统初始化。

#include "abov_m0s11.h"

// 配置系统时钟
void configure_system_clock(void) {
    // 使能HXT
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;  // 使能12MHz外部高速晶振

    // 等待HXT稳定
    while (!(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk));

    // 选择HXT作为系统时钟源
    CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | CLK_CLKSEL0_HCLKSEL_HXT;
}

// 配置时钟分频
void configure_clock_dividers(void) {
    // 配置AHB分频器,分频比为1
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | CLK_CLKDIV_HCLKDIV(1);

    // 配置APB分频器,分频比为2
    CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_PCLKDIV_Msk) | CLK_CLKDIV_PCLKDIV(2);
}

// 配置低电压检测复位
void configure_low_voltage_reset(void) {
    // 选择LVR阈值为2.7V
    SYS->LVDCON = (SYS->LVDCON & ~SYS_LVDCON_LVD_VLSEL_Msk) | SYS_LVDCON_LVD_VLSEL_2_7V;

    // 使能LVR
    SYS->LVDCON |= SYS_LVDCON_LVR_EN_Msk;
}

// 读取复位状态寄存器
void read_reset_status(void) {
    // 读取复位状态寄存器
    uint32_t reset_status = SYS->RSTSRC;

    // 判断复位来源
    if (reset_status & SYS_RSTSRC_PORST_IF_Msk) {
        printf("上电复位\n");
    }
    if (reset_status & SYS_RSTSRC_PDRST_IF_Msk) {
        printf("掉电复位\n");
    }
    if (reset_status & SYS_RSTSRC_EXTRST_IF_Msk) {
        printf("外部复位\n");
    }
    if (reset_status & SYS_RSTSRC_SWRST_IF_Msk) {
        printf("软件复位\n");
    }
    if (reset_status & SYS_RSTSRC_WDRST_IF_Msk) {
        printf("看门狗复位\n");
    }
    if (reset_status & SYS_RSTSRC_LVRST_IF_Msk) {
        printf("低电压检测复位\n");
    }

    // 清除复位标志
    SYS->RSTSRC = reset_status;
}

// 复位处理函数
void reset_handler(void) {
    // 配置系统时钟
    configure_system_clock();

    // 配置时钟分频
    configure_clock_dividers();

    // 配置低电压检测复位
    configure_low_voltage_reset();

    // 初始化GPIO
    GPIO->MODE = (GPIO->MODE & ~GPIO_MODE_MODE0_Msk) | GPIO_MODE_MODE0_INPUT;

    // 初始化定时器
    TIMER->TCSR0 = (TIMER->TCSR0 & ~TIMER_TCSR0_PSC_Msk) | TIMER_TCSR0_PSC(127);  // 设置预分频器
    TIMER->TCSR0 |= TIMER_TCSR0_EN_Msk;  // 使能定时器

    // 初始化中断控制器
    NVIC_EnableIRQ(TIMER0_IRQn);  // 使能定时器0中断

    // 读取复位状态
    read_reset_status();
}

// 定时器0中断处理函数
void TIMER0_IRQHandler(void) {
    // 清除定时器0中断标志
    TIMER->TCSR0 |= TIMER_TCSR0_IF_Msk;

    // 处理定时器0中断
    printf("定时器0中断\n");
}

// 复位向量表
__attribute__((section(".isr_vector"))) const uint32_t isr_vector[] = {
    (uint32_t)&__stack_end__,  // 堆栈指针
    (uint32_t)&reset_handler,  // 复位处理函数
    (uint32_t)&NMI_Handler,    // NMI中断处理函数
    (uint32_t)&HardFault_Handler,  // 硬故障中断处理函数
    (uint32_t)&MemManage_Handler,  // 内存管理中断处理函数
    (uint32_t)&BusFault_Handler,   // 总线故障中断处理函数
    (uint32_t)&UsageFault_Handler,  // 使用故障中断处理函数
    0, 0, 0, 0,  // 保留
    0, 0, 0, 0,  // 保留
    (uint32_t)&SVCall_Handler,  // 系统调用中断处理函数
    (uint32_t)&DebugMon_Handler,  // 调试监控中断处理函数
    0,  // 保留
    (uint32_t)&PendSV_Handler,  // 挂起服务中断处理函数
    (uint32_t)&SysTick_Handler,  // 系统节拍定时器中断处理函数
    (uint32_t)&TIMER0_IRQHandler,  // 定时器0中断处理函数
    // 其他中断处理函数
};

// 缺省中断处理函数
void NMI_Handler(void) __attribute__((weak, alias("default_handler")));
void HardFault_Handler(void) __attribute__((weak, alias("default_handler")));
void MemManage_Handler(void) __attribute__((weak, alias("default_handler")));
void BusFault_Handler(void) __attribute__((weak, alias("default_handler")));
void UsageFault_Handler(void) __attribute__((weak, alias("default_handler")));
void SVCall_Handler(void) __attribute__((weak, alias("default_handler")));
void DebugMon_Handler(void) __attribute__((weak, alias("default_handler")));
void PendSV_Handler(void) __attribute__((weak, alias("default_handler")));
void SysTick_Handler(void) __attribute__((weak, alias("default_handler")));

// 缺省中断处理函数
void default_handler(void) {
    while (1) {
        // 处理缺省中断
    }
}

int main(void) {
    // 跳转到复位处理函数
    reset_handler();

    // 主程序
    while (1) {
        // 应用代码
    }
}

总结

本章详细介绍了ABOV M0S11系列单片机的时钟系统和复位管理。时钟系统包括内部和外部时钟源、时钟树、时钟配置和时钟分频。复位管理包括多种复位源、复位配置、复位状态寄存器、复位处理函数和复位向量表。通过示例代码,我们展示了如何配置和初始化这些系统功能,以便在实际应用中确保单片机的稳定性和可靠性。希望这些内容能够帮助您更好地理解和使用ABOV M0S11系列单片机。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值