【凌鸥LKS32】基础篇(一)·点亮一颗LED
目录
1. 芯片简介
LKS32MC07x 是南京凌鸥创芯推出的电机控制专用工业级 MCU,搭载 96MHz Cortex‑M0 内核,集成完整模拟前端与电机控制外设,主打 BLDC/PMSM FOC 驱动场景。
特性:
○ 96MHz 32 位 Cortex-M0 内核,32bit 硬件除法协处理器
○ 4 通道 DMA
○ 10uA 低功耗休眠模式
○ -40~105℃工业级工作温度范围
○ MCU 采用 2.5V~5.5V 单电源供电,内部集成数字供电 LDO
○ 超强抗静电和群脉冲能力
○ 64/128kB Flash,数据防盗功能
○ 12kB RAM
○ 内置 8MHz 高精度 RC 时钟,全温度范围精度 ±1%
○ 内置 32kHz 低速时钟,供低功耗模式使用
○ 内部 PLL 可提供最高 96MHz 时钟
系统框图:


2. GPIO简介
LKS32MC07x 系列芯片共集成了 4 组 GPIO,每组包含 16 个 GPIO。部分 GPIO 可以作为系统的休眠模式唤醒源。部分 GPIO 可以用作外部中断源输入。功能框图如下:

| 寄存器标识 | 中文名称 | 功能说明 |
|---|---|---|
| Pm[n] | 引脚 Pm 第 n 号通道 | MCU 对外物理引脚 |
| GPIOm_PUE[n] | 上拉使能控制 | 开关:开启 / 关闭内部上拉电阻 |
| Pull-up Resister | 上拉电阻 | 芯片内置上拉电阻 |
| GPIOm_PDO[n] | 输出数据寄存器 | 输出电平(0 = 低,1 = 高) |
| GPIOm_POE[n] | 输出使能 | 开启推挽输出缓冲器 |
| GPIOm_PIE[n] | 输入使能 | 开启数字输入通路 |
| GPIOm_PDI[n] | 输入数据寄存器 | 读取引脚当前电平 |
| Analog Signal | 模拟信号通路 | ADC 模拟输入通道,串联约 200Ω 保护电阻 |
详细的可以查看官方手册:LKS32MC07x_User_Manual_v1.69,之后会打包放到最下方。
3. 代码编写
3.1 GPIO初始化
首先来了解一下GPIO功能配置结构体句柄:
/**
*@brief GPIO功能配置结构体句柄
*/
typedef struct
{
u32 GPIO_Pin; ///< 要配置的引脚
u32 GPIO_Mode; ///< GPIO模式
u32 GPIO_PuPd; ///< 上拉使能
u32 GPIO_PODEna; ///< 开漏使能
u32 GPIO_PFLT;
} GPIO_InitTypeDef;
我们这里只是点灯,所以只需要配置前两项即可,其他两项默认DISABLE:
void GPIO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Pin = LED1_PIN;
GPIO_Init(LED1_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Pin = LED2_PIN;
GPIO_Init(LED2_PORT, &GPIO_InitStruct);
}
其中宏定义引脚如下:
#define LED1_PIN GPIO_Pin_6
#define LED1_PORT GPIO0
#define LED2_PIN GPIO_Pin_7
#define LED2_PORT GPIO0
引脚功能配置为推挽输出模式,其中GPIO的几种输入输出模式:
/**
*@brief GPIO模式选择枚举
*/
typedef enum
{
GPIO_Mode_IN = 0x00, /*!< GPIO 输入&高阻,模拟和数字同时生效*/
GPIO_Mode_OUT = 0x01, /*!< GPIO 输出*/
GPIO_Mode_ANA = 0x02, /*!< GPIO 高阻*/
GPIO_Mode_IO = 0x03
} GPIOMode_TypeDef;
| 枚举值 | 值 | PIE (输入) | POE (输出) | 用途 |
|---|---|---|---|---|
GPIO_Mode_IN | 0x00 | ✅ | ❌ | 输入模式 — 数字输入,模拟输入也可同时生效 |
GPIO_Mode_OUT | 0x01 | ❌ | ✅ | 输出模式 — 推挽输出,驱动 LED/外设 |
GPIO_Mode_ANA | 0x02 | ✅ | ❌ | 模拟模式 — ADC 采样、比较器输入 |
GPIO_Mode_IO | 0x03 | ✅ | ✅ | 双向模式 — 同时使能输入输出,用于开漏总线 |
3.2 延时实现
此时还未使用定时器,就是要系统延时,主要是调用空操作指令:__NOP():
| 属性 | 说明 |
|---|---|
| 指令 | Cortex-M0 的 NOP 汇编指令 |
| 耗时 | 1 个 CPU 时钟周期 |
| 作用 | CPU 空转一拍,不做任何操作 |
| 用途 | 纯粹消耗时间,防止编译器优化掉空循环 |
代码如下:
void SoftDelay(u32 cnt)
{
volatile u32 t_cnt;
for(t_cnt = 0; t_cnt < cnt; t_cnt++)
{
__NOP();
}
}
延时时间计算公式:
延时时间 = 循环次数 × 每循环周期数 ÷ CPU 频率
| CPU 频率 | 每循环 | SoftDelay(N) 延时公式 |
|---|---|---|
| 96 MHz (PLL) | 7 cycles | T ≈ N × 0.073 µs |
| 8 MHz (HSI 默认) | 7 cycles | T ≈ N × 0.875 µs |
举个例子:
SoftDelay(N) | 8MHz | 96MHz |
|---|---|---|
SoftDelay(100) | 87.5 µs | 7.3 µs |
SoftDelay(0xFFFFF) = 1,048,575 | ~917 ms | ~76 ms |
SoftDelay(0x68A000) ≈ 6,857,000 | ~6 s | ~500 ms |
这里我们想要使用96MHz,那么可以如下操作,进行重新配置时钟:
void Clock_Init(void)
{
SYS_WR_PROTECT = 0x7a83; /* 解除系统寄存器写保护 */
SYS_AFE_REG5 = BIT15; /* BIT15:PLLPDN 开PLL */
SoftDelay(100); /* 延时100us, 等待PLL稳定 21.4.17*/
SYS_CLK_CFG = 0x000001ff; /* BIT8:0: CLK_HS,1:PLL | BIT[7:0]CLK_DIV | 1ff对应96M时钟 */
SYS_WR_PROTECT = 0; /* 关闭系统寄存器写操作*/
}
LKS32MC07x 的关键系统寄存器(时钟、电源、复位相关)默认处于写保护状态,防止误操作。只有输入0x7a83这个特定值才能解锁保护状态,进行写保护。
系统复位时,PLL 默认关闭,HSI 默认开启,即系统上电选择HSI 时钟,8MHz 作为系统主时
钟进行工作,从而保证系统上电之初功耗处于较低水平。所以这里我们开启PLL供电,启动内部倍频电路,然后延时等待一段时间,配置PLL输出分频参数。

对于为什么0x1FF代表96MHz,根据数据手册,寄存器配置部分,可以看到当第[9:8]位值为1表示使用PLL,第[7:0]位为0xFF表示1分频,也就是不分频,使用的是96MHz的时钟频率。
PLL 经过n/8 分频后,可以得到96MHz×n/8 的高速时钟,作为系统主时钟MCLK。系
统主时钟MCLK可以通过SYS_CLK_CFG.CLK_DIV进行n/8分频,可以产生12,24,48MHz等频率值。

然后将其写入SystemInit()函数当中,系统上电自动执行SystemInit()函数:
void SystemInit(void)
{
Clock_Init(); /* 时钟初始化 */
}
3.3 硬件初始化
主要通过__disable_irq();和__enable_irq();进行开关中断操作,形成临界区保护,防止操作被打断:
void Hardware_init(void)
{
__disable_irq(); /* 关闭中断 中断总开关 */
SYS_WR_PROTECT = 0x7a83;
IWDG_DISABLE(); /* 关闭看门狗*/
GPIO_init(); /* GPIO初始化 */
SoftDelay(100); /* 延时等待硬件初始化稳定 */
__enable_irq(); /* 开启总中断 */
}
这里关掉看门狗的主要原因是防止断点暂停时 WDT 超时,导致频繁喂狗,系统无法正常运行。
3.4 主函数功能实现
主函数直接调用,大概可以实现500ms交替闪烁一次(具体时间因为可能是估算值所以不准):
int main(void)
{
Hardware_init(); /* 硬件初始化 */
while(1)
{
GPIO_SetBits(LED1_PORT, LED1_PIN); /* LED1 亮*/
GPIO_ResetBits(LED2_PORT, LED2_PIN); /* LED2 灭*/
SoftDelay(0x68A000);
GPIO_ResetBits(LED1_PORT, LED1_PIN); /* LED1 灭*/
GPIO_SetBits(LED2_PORT, LED2_PIN); /* LED2 亮*/
SoftDelay(0x68A000);
}
}
可以发现两颗LED交替闪烁。
4. 流水灯设计
我们通过原理图可以看到,LED3的连接方式和其他两个不同,整理一下宏定义:
#define LED1_PIN GPIO_Pin_6
#define LED1_PORT GPIO0
#define LED1_ON GPIO_SetBits(LED1_PORT, LED1_PIN)
#define LED1_OFF GPIO_ResetBits(LED1_PORT, LED1_PIN)
#define LED2_PIN GPIO_Pin_7
#define LED2_PORT GPIO0
#define LED2_ON GPIO_SetBits(LED2_PORT, LED2_PIN)
#define LED2_OFF GPIO_ResetBits(LED2_PORT, LED2_PIN)
#define LED3_PIN GPIO_Pin_3
#define LED3_PORT GPIO0
#define LED3_ON GPIO_ResetBits(LED3_PORT, LED3_PIN)
#define LED3_OFF GPIO_SetBits(LED3_PORT, LED3_PIN)
初始化部分,将LED3初始化:
void GPIO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Pin = LED1_PIN;
GPIO_Init(LED1_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Pin = LED2_PIN;
GPIO_Init(LED2_PORT, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Pin = LED3_PIN;
GPIO_Init(LED3_PORT, &GPIO_InitStruct);
}
来到主函数:
#include "lks32mc07x_lib.h"
#include "hardware_init.h"
int main(void)
{
Hardware_init(); /* 硬件初始化 */
while(1)
{
LED1_ON; /* LED1 亮*/
LED2_OFF; /* LED2 灭*/
LED3_OFF; /* LED3 灭*/
SoftDelay(0x300000);
LED1_OFF; /* LED1 灭*/
LED2_ON; /* LED2 亮*/
LED3_OFF; /* LED3 亮*/
SoftDelay(0x300000);
LED1_OFF; /* LED1 灭*/
LED2_OFF; /* LED2 亮*/
LED3_ON; /* LED3 亮*/
SoftDelay(0x300000);
}
}
导入发现流水灯闪烁。


更多推荐
所有评论(0)