本帖最后由 doghead 于 2025-2-11 11:30 编辑
/******************************************************************************
* Copyright (C) 2017, Xiaohua Semiconductor Co.,Ltd All rights reserved.
*
* 此软件为小华半导体股份有限公司所有并发布。
*/
#include "adc.h" // ADC 相关头文件
#include "gpio.h" // GPIO 相关头文件
#include "bgr.h" // BGR (带隙基准) 相关头文件
#include "stdio.h" // 标准输入输出 (printf)
#include "uart.h" // UART (串口) 相关头文件
#include "sysctrl.h" // 系统控制相关头文件 (时钟等)
#define VCC 3.3f // 供电电压
// 全局变量,用于存储 ADC 转换结果 (声明为 volatile,防止优化)
volatile uint32_t u32AdcRestult0; // PC00
volatile uint32_t u32AdcRestult1; // PC01
// 函数声明
void App_AdcPortInit(void); // 初始化 ADC 端口 (GPIO)
void App_AdcInit(void); // 初始化 ADC 模块
void App_AdcJqrCfg(void); // 配置 ADC 队列扫描模式 (JQR)
void App_PortInit(void); // 初始化 UART 端口 (GPIO)
void App_UartCfg(void); // 配置 UART 模块
float ConvertToVoltage(uint32_t sensorValue); // 将 ADC 值转换为电压
void delay_ms(uint32_t ms); // 简单的毫秒延时函数
// 主函数
int main(void) {
App_AdcPortInit(); // 初始化 ADC 端口
App_AdcInit(); // 初始化 ADC 模块
App_AdcJqrCfg(); // 配置 ADC 队列扫描
App_PortInit(); // 初始化 UART 端口
App_UartCfg(); // 配置 UART 模块
__enable_irq(); // 使能全局中断
while (1) {
Adc_JQR_Start(); // 启动 ADC 队列扫描转换
delay_ms(500); // 延时 500 毫秒
float voltage0 = ConvertToVoltage(u32AdcRestult0); // 转换通道 0 电压 (PC00)
float voltage1 = ConvertToVoltage(u32AdcRestult1); // 转换通道 1 电压 (PC01)
// 打印 ADC 值和对应的电压值
printf("ADC Channel 0 (PC00): %lu -> Voltage: %.3f V\n", u32AdcRestult0, voltage0);
printf("ADC Channel 1 (PC01): %lu -> Voltage: %.3f V\n", u32AdcRestult1, voltage1);
}
}
// ADC 中断处理函数
void Adc_IRQHandler(void) {
if (TRUE == Adc_GetIrqStatus(AdcMskIrqJqr)) { // 检查是否是 JQR 中断
Adc_ClrIrqStatus(AdcMskIrqJqr); // 清除 JQR 中断标志
// ************************ 调试代码 **************************
uint32_t localResult0 = Adc_GetJqrResult(AdcJQRCH0MUX); // 直接读取 ADC 结果寄存器 (PC00)
uint32_t localResult1 = Adc_GetJqrResult(AdcJQRCH1MUX); // 直接读取 ADC 结果寄存器 (PC01)
// 在中断中打印 ADC 值,用于调试
printf("Interrupt: PC00=%lu, PC01=%lu\n", localResult0, localResult1);
// ************************ 调试代码 **************************
u32AdcRestult0 = localResult0; // 将局部变量的值赋给全局变量 (PC00)
u32AdcRestult1 = localResult1; // 将局部变量的值赋给全局变量 (PC01)
}
}
// 初始化 ADC 端口 (GPIO)
void App_AdcPortInit(void) {
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); // 使能 GPIO 外设时钟
// 将PC00和PC01配置为AIN8和AIN9
Gpio_SetAnalogMode(GpioPortC, GpioPin0); // PC0 作为 AIN8 (ADC 输入)
Gpio_SetAnalogMode(GpioPortC, GpioPin1); // PC1 作为 AIN9 (ADC 输入)
}
// 初始化 ADC 模块
void App_AdcInit(void) {
stc_adc_cfg_t stcAdcCfg; // ADC 配置结构体
DDL_ZERO_STRUCT(stcAdcCfg); // 初始化结构体
Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE); // 使能 ADC/BGR 外设时钟
Bgr_BgrEnable(); // 使能 BGR (带隙基准)
stcAdcCfg.enAdcMode = AdcScanMode; // 扫描模式
stcAdcCfg.enAdcClkDiv = AdcMskClkDiv1; // ADC 时钟分频:1
stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle8Clk; // 采样周期:8 个时钟周期
stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelAVDD; // 参考电压:AVDD (VCC)
stcAdcCfg.enAdcOpBuf = AdcMskBufDisable; // 关闭 OP BUF
stcAdcCfg.enInRef = AdcMskInRefDisable; // 关闭内部参考电压
stcAdcCfg.enAdcAlign = AdcAlignRight; // 转换结果右对齐
Adc_Init(&stcAdcCfg); // 初始化 ADC
}
// 配置 ADC 队列扫描模式 (JQR)
void App_AdcJqrCfg(void) {
stc_adc_jqr_cfg_t stcAdcJqrCfg; // JQR 配置结构体
DDL_ZERO_STRUCT(stcAdcJqrCfg); // 初始化结构体
stcAdcJqrCfg.bJqrDmaTrig = FALSE; // 关闭 DMA 触发
stcAdcJqrCfg.u8JqrCnt = 2; // 扫描 2 个通道. Crucially changed to 2
Adc_JqrModeCfg(&stcAdcJqrCfg); // 配置 JQR 模式
Adc_CfgJqrChannel(AdcJQRCH0MUX, AdcExInputCH8); // 通道 0: AIN8 (PC00)
Adc_CfgJqrChannel(AdcJQRCH1MUX, AdcExInputCH9); // 通道 1: AIN9 (PC01)
Adc_EnableIrq(); // 使能 ADC 中断
EnableNvic(ADC_IRQn, IrqLevel3, TRUE); // 使能 NVIC 中断 (设置优先级)
}
// 将 ADC 值转换为电压
float ConvertToVoltage(uint32_t sensorValue) {
float maxADCValue = 4095.0f; // 12 位 ADC 最大值
return (float)sensorValue * VCC / maxADCValue; // 计算电压
}
// UART fputc 重定向,用于 printf
int fputc(int ch, FILE *f) {
Uart_SendDataPoll(M0P_UART0, (uint8_t)ch); // 使用轮询发送 UART 数据
return ch;
}
// 初始化 UART 端口 (GPIO)
void App_PortInit(void) {
stc_gpio_cfg_t stcGpioCfg; // GPIO 配置结构体
DDL_ZERO_STRUCT(stcGpioCfg); // 初始化结构体
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); // 使能 GPIO 外设时钟
stcGpioCfg.enDir = GpioDirOut; // TX 引脚配置为输出
Gpio_Init(GpioPortA, GpioPin9, &stcGpioCfg);
Gpio_SetAfMode(GpioPortA, GpioPin9, GpioAf1); // PA9 作为 UART0 TX
stcGpioCfg.enDir = GpioDirIn; // RX 引脚配置为输入
Gpio_Init(GpioPortA, GpioPin10, &stcGpioCfg);
Gpio_SetAfMode(GpioPortA, GpioPin10, GpioAf1); // PA10 作为 UART0 RX
}
// 配置 UART 模块
void App_UartCfg(void) {
stc_uart_cfg_t stcCfg; // UART 配置结构体
DDL_ZERO_STRUCT(stcCfg); // 初始化结构体
Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0, TRUE); // 使能 UART0 外设时钟
stcCfg.enRunMode = UartMskMode3; // 模式 3
stcCfg.enStopBit = UartMsk1bit; // 1 位停止位
stcCfg.enMmdorCk = UartMskEven; // 偶校验
stcCfg.stcBaud.u32Baud = 9600; // 波特率 9600
stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div; // 时钟分频
stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq(); // 获取 PCLK 频率
Uart_Init(M0P_UART0, &stcCfg); // 初始化 UART
Uart_ClrStatus(M0P_UART0, UartRC); // 清除接收标志
Uart_EnableIrq(M0P_UART0, UartRxIrq); // 使能接收中断
//Uart_SetTransMode(M0P_UART0, UartMskTx); // 使能 UART 发送
Uart_EnableIrq(M0P_UART0,UartTxIrq); // (错误! 不要使用此行!)
}
// 简单的毫秒延时函数
void delay_ms(uint32_t ms) {
volatile uint32_t i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 8000; j++); // 调整循环次数以获得准确延时
}
}

|