GPIO 配置
一、GPIO引脚
| 引脚 | 对应位 | 当前用途 | 能不能直接改 |
|---|---|---|---|
INT0_2 |
EPORT0 bit2 | 编码器按键(下降沿中断) | 需先 encoder_on = 0 |
INT0_3 |
EPORT0 bit3 | 空闲 | 可直接用 |
INT0_6 |
EPORT0 bit6 | 编码器 B 相 | 需先 encoder_on = 0 |
INT0_7 |
EPORT0 bit7 | 编码器 A 相 | 需先 encoder_on = 0 |
编码器开关在 User/module_select.h:
#define encoder_on 1 // 改成 0 释放 INT0_2/6/7三个 PWM 脚,其中 PWM1_2 已被蜂鸣器占用,剩余空闲PWM:
| 引脚 | PWM 模块 | 通道 | 预分频 | 状态 |
|---|---|---|---|---|
PWM1_0 |
PWM1 | CH0 | CP0 |
空闲 |
PWM1_1 |
PWM1 | CH1 | CP0 |
空闲 |
PWM0_3 |
PWM0 | CH3 | CP1 |
空闲 |
二、配置 GPIO
第 1 步:把 AIN 切成 GPIO
这四个脚默认是 ADC 输入,当 GPIO 用必须先关掉对应通道的 ADC,
否则读写全部无效。改 OPTION->ADCCDISR 的对应位:
| 引脚 | 位掩码 |
|---|---|
INT0_2 |
1 << 2 |
INT0_3 |
1 << 3 |
INT0_6 |
1 << 6 |
INT0_7 |
1 << 7 |
写法(以同时开 INT0_3 为例,掩码 0x08):
OPTION->U16_ADCCDISR.ADCCDISTEST = 1;
OPTION->U16_ADCCDISR.ADCCDISTEST = 2;
OPTION->U16_ADCCDISR.ADCCDISTEST = 3; // ① 解锁序列 1→2→3
OPTION->U16_ADCCDISR.ADCCDIS |= (1 << 3); // ② INT0_3 切 GPIO多个脚一起开就按位或:(1<<2) | (1<<3) | (1<<6) | (1<<7) = 0xCC。
参考现有写法:
Widget/uiEncoder.c的Encoder_Init()用value |= 0xC4;
开的就是 bit2/6/7;Function/if_port.c用|= (1<<1)开 LCD_RST。这一步是可逆的 —— 把同一位清 0 就恢复 ADC 功能,见第三节。
第 2 步:设方向与上下拉
EPORT0->EPDDR |= (1 << 3); // 输出
EPORT0->EPDDR &= ~(1 << 3); // 输入
EPORT0->EPPUE |= (1 << 3); // 开上拉第 3 步:读写
EPORT0->EPDR |= (1 << 3); // 输出高
EPORT0->EPDR &= ~(1 << 3); // 输出低
EPORT0->EPBSR = (1 << 3); // 同上,原子置位(推荐)
EPORT0->EPBCR = (1 << 3); // 原子清零
level = (EPORT0->EPPDR >> 3) & 0x01; // 读输入电平寄存器速查:
| 寄存器 | 作用 |
|---|---|
EPDDR |
方向,1 = 输出 |
EPPUE |
上拉使能 |
EPDR |
写输出电平 |
EPPDR |
读引脚电平 |
EPBSR / EPBCR |
原子置位 / 清零 |
EPIER |
中断使能 |
EPPAR |
中断触发方式 |
EPFR |
中断标志(写 1 清) |
三、切换回 ADC(复用回 AIN)
规则只有一条:同一个 ADCCDIS 位,置 1 = GPIO,清 0 = ADC。
ADCCDIS 位 |
引脚功能 |
|---|---|
| 1 | GPIO(INT0_x) |
| 0 | ADC(AIN_x) |
编号一一对应,库里也是成对给的:
| 引脚 | 切成 GPIO | 切回 ADC | 采样用 |
|---|---|---|---|
INT0_2 / AIN2 |
PIN_EPORT0_2() |
PIN_ADC_CH2_Default() |
ADC_CH2 |
INT0_3 / AIN3 |
PIN_EPORT0_3() |
PIN_ADC_CH3_Default() |
ADC_CH3 |
INT0_6 / AIN6 |
PIN_EPORT0_6() |
PIN_ADC_CH6_Default() |
ADC_CH6 |
INT0_7 / AIN7 |
PIN_EPORT0_7() |
PIN_ADC_CH7_Default() |
ADC_CH7 |
直接写寄存器 —— 与第 1 步唯一差别是 |= 换成 &= ~:
OPTION->U16_ADCCDISR.ADCCDISTEST = 1;
OPTION->U16_ADCCDISR.ADCCDISTEST = 2;
OPTION->U16_ADCCDISR.ADCCDISTEST = 3; // 解锁序列 1→2→3
OPTION->U16_ADCCDISR.ADCCDIS &= ~(1 << 3); // INT0_3 还给 ADC采样:
#include "lt168_adc.h"
ADC_Init(); // 整个程序调一次
uint16_t val = Get_ADC_Val(ADC_CH3); // 12 位,0~4095- 分辨率 12 位(
ADC_Init()里ADC->U32_ADC_CFGR1.RES = 0) Get_ADC_Val()是单次阻塞采样,别放在时序要求紧的地方- 除外部通道外还能采内部通道:
VREFINT(14)、Temper_Sensor(15) - 完整例程:
Lib/src/lt168_adc.c的ADC_Demo()
GPIO 和 ADC 不能同时用同一个脚 —— 切成 GPIO 后,该脚的模拟输入就失效了。
四、配置 PWM 输出
第 1 步:切到 PWM 功能
PWM 与 QSPI2 共用引脚,由 OPTION->CCR bit8 决定:
PIN_PWM_Default(); // 清 bit8 → 引脚给 PWM
// PIN_QSPI2(); // 置 bit8 → 引脚给 QSPI2第 2 步:配频率与占空比
寄存器按通道区分,预分频器由 channel / 2 决定(见 lt168_pwm.c:60):
| 通道 | 预分频 | 时钟选择 | 周期 | 占空比 | 使能 |
|---|---|---|---|---|---|
CH0(PWM1_0) |
PPR.CP0 |
PCSR.CSR0 |
PCNR0 |
PCMR0 |
PCR.CH0EN |
CH1(PWM1_1) |
PPR.CP0 |
PCSR.CSR1 |
PCNR1 |
PCMR1 |
PCR.CH1EN |
CH3(PWM0_3) |
PPR.CP1 |
PCSR.CSR3 |
PCNR3 |
PCMR3 |
PCR.CH3EN |
PWM1_0 输出 1 kHz、占空比 50%:
PIN_PWM_Default();
PWM1->U32_PPR.CP0 = 0; // CH0/CH1 用 CP0,0 = 不分频
PWM1->U32_PCSR.CSR0 = 2; // 8 分频 → 168/8 = 21MHz
PWM1->PCNR0 = 20999; // 周期:21MHz / 21000 = 1kHz
PWM1->PCMR0 = 10500; // 占空比 10500/21000 = 50%
PWM1->U32_PCR.CH0EN = 1; // 使能通道
PWM1->U32_PPCR.PDDR_0 = 1; // 引脚设为输出运行中改占空比:
PWM1->PCMR0 = 5250; // 25%PWM0_3(注意是 PWM0 模块、CH3、用 CP1):
PIN_PWM_Default();
PWM0->U32_PPR.CP1 = 0;
PWM0->U32_PCSR.CSR3 = 2; // 8 分频 → 21MHz
PWM0->PCNR3 = 20999; // 1 kHz
PWM0->PCMR3 = 10500; // 50%
PWM0->U32_PCR.CH3EN = 1;
PWM0->U32_PPCR.PDDR_3 = 1;频率怎么算
f = 168MHz / (CSR 分频) / (CP + 1) / (PCNR + 1)CSR 取值与分频的对应:
| CSR | 0 | 1 | 2 | 3 | 其它 |
|---|---|---|---|---|---|
| 分频 | 2 | 4 | 8 | 16 | 1 |
例如 CSR=2(8 分频)、CP=0、PCNR=20999:168MHz / 8 / 1 / 21000 = 1 kHz。
已在用的参考配置:
bsp.c里蜂鸣器把 PWM1 的 CH2 配成 2.1 kHz / 50%
(CSR2=2、CP1=0、PCNR2=9999、PCMR2=5000)。
五、注意事项
| 项 | 说明 |
|---|---|
| 必须先切复用 | INT0_x 不写 ADCCDISR 就还是 ADC,读写全无效 |
| GPIO / ADC 互斥 | 同一个脚只能二选一,切成 GPIO 后模拟输入失效,切回 ADC 见第三节 |
| 解锁序列 | 写 ADCCDISR 前要走 ADCCDISTEST 1→2→3,直接赋值无效 |
| INT0_2/6/7 被编码器占 | 用它们之前先 #define encoder_on 0,否则两边冲突 |
| PWM vs QSPI2 | 同一个 bit8 控制;本工程没调 PIN_QSPI2(),PWM 可用 |
CP0/CP1 是共享的 |
CH0 和 CH1 共用 CP0,改一个会影响另一个通道的分频 |
PWM1_2 别动 |
那是蜂鸣器;好在它在 CP1,与 PWM1_0/1 的 CP0 互不干扰 |
| 清中断标志 | EPFR 写 1 清,不清会反复进中断 |
| 电平中断 | 高/低电平中断不可常开,本工程用的都是边沿中断 |
六、已用的 GPIO
| 引脚 | 用途 |
|---|---|
INT0_0 / INT0_4 |
触摸(CTP)SDA / SCL |
INT0_1 / INT0_5 |
触摸 INT(兼 LCD_RST)/ 触摸 RST |
EPORT1_0 |
LT758 WAIT 握手脚,卡住会导致 4 秒看门狗复位 |
PWM1_2 |
蜂鸣器 |
最后编辑:罗珍雪 更新时间:2026-11-02 20:02