2023-10-19 13:56:26 +08:00

326 lines
9.5 KiB
C

/*
* main.c
*
* Created on: 2023年7月4日
* Author: User
*/
#include "main.h"
#include <STDIO.H>
#include <STDLIB.H>
#include <STRING.H>
#include "ADC.h"
#include "GPIO.h"
#include "NTC100K.h"
#include "UART.h"
#include "delay.h"
#include "ring.h"
#include "timer.h"
#include "ws2812.h"
#define NTC_CHANNEL ADC_CH1
#define ADC_START_NTC ADC_CONTR = (ADC_CONTR & 0xf0) | ADC_START | NTC_CHANNEL;
#define PWM_ARR 199 // PWM频率设置 20M / (199 + 1) = 100KHz => 10us
static u8 tick; // 每秒计时的标志 1s
static u8 update; // 更新PWM的标志 10ms
static u32 sysTime; // 系统计时时钟 1ms
static u16 curTemp; // 当前温度
static u16 curPwm; // 当前PWM百分比
// NTC的ADC数据缓冲区
static u16 xdata ntcAdcBuf[ADC_BUF_LENGTH];
// static u32 led[7] = {WS2812B_RED, WS2812B_ORANGE, WS2812B_YELLOW, WS2812B_GREEN,
// WS2812B_CYAN, WS2812B_BLUE, WS2812B_PURPLE};
// static u32 led[7] = {WS2812B_CYAN, WS2812B_CYAN, WS2812B_CYAN, WS2812B_CYAN, WS2812B_CYAN, WS2812B_CYAN,
// WS2812B_CYAN}; static u8 *p_led = led, v_led = 0, b_led = 0, b_num = 0; static u8 num = 0;
/**
* 主函数
*/
void main() {
init();
while (1) core();
}
static void GPIOInit() {
GPIO_InitTypeDef GPIO_InitStructure;
// 准双向端口
GPIO_InitStructure.Mode = GPIO_PullUp;
GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Inilize(GPIO_P3, &GPIO_InitStructure); // P30,P31,P32,P33,P35,P36,P37
GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Inilize(GPIO_P1, &GPIO_InitStructure); // P10,P13,P14,P15,P16,P17
GPIO_InitStructure.Pin = GPIO_Pin_4;
GPIO_Inilize(GPIO_P5, &GPIO_InitStructure); // P54
// 推挽端口
GPIO_InitStructure.Mode = GPIO_OUT_PP;
GPIO_InitStructure.Pin = GPIO_Pin_4;
GPIO_Inilize(GPIO_P3, &GPIO_InitStructure); // P34
GPIO_InitStructure.Pin = GPIO_Pin_2;
GPIO_Inilize(GPIO_P1, &GPIO_InitStructure); // P12
// 高阻端口
GPIO_InitStructure.Mode = GPIO_HighZ;
GPIO_InitStructure.Pin = GPIO_Pin_1;
GPIO_Inilize(GPIO_P1, &GPIO_InitStructure); // P11
}
static void uartInit() {
COMx_InitDefine COMx_InitStructure; // 结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx; // 8N1模式
COMx_InitStructure.UART_BRT_Use = BRT_Timer1; // 选择波特率发生器
COMx_InitStructure.UART_BaudRate = 115200ul; // 波特率 115200
COMx_InitStructure.UART_RxEnable = TRUE; // 不需要接收
COMx_InitStructure.BaudRateDouble = DISABLE; // 波特率不加倍
COMx_InitStructure.UART_Interrupt = ENABLE; // 中断使能
COMx_InitStructure.UART_Priority = Priority_0; // 中断优先级
UART_Configuration(UART1, &COMx_InitStructure); // 初始化串口1
}
static void ADCInit() {
ADC_InitTypeDef ADC_InitStructure; // 结构定义
ADC_InitStructure.ADC_SMPduty = 31; // ADC 模拟信号采样时间控制
ADC_InitStructure.ADC_Speed = ADC_SPEED_2X1T; // ADC 工作时钟频率
ADC_InitStructure.ADC_Power = ENABLE; // ADC 电源打开
ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED; // ADC 结果调整
ADC_InitStructure.ADC_Priority = Priority_0; // ADC 优先级
ADC_InitStructure.ADC_Interrupt = DISABLE; // ADC 禁用中断
ADC_InitStructure.ADC_CsSetup = 0; // ADC 通道选择时间控制 0(默认),1
ADC_InitStructure.ADC_CsHold = 1; // ADC 通道选择保持时间控制 0,1(默认),2,3
ADC_Inilize(&ADC_InitStructure); // 初始化ADC
// ADC_CONTR = ADC_CONTR | ADC_EPWMT; //使能PWM同步触发
ADC_START_NTC; // 启动ADC转换
}
static void PWMInit() {
EAXSFR();
// // 配置PWM4 用于控制WS2812
// PWM4_USE_P34P33();
// PWMA_CC4E_Disable(); // 关闭输入捕获/比较输出
// PWMA_CC4NE_Disable(); // 关闭比较输出
// PWMA_OC4_RelosdDisable(); // 禁止 OC4PE 输出比较的预装载功能
// PWMA_CC4S_Direction(CCAS_OUTPUT); // CCnS仅在通道关闭时才是可写的
// PWMA_OC4ModeSet(CCMRn_PWM_MODE1); // 设置输出比较模式
// PWMA_CC4E_Enable(); // 开启比较输出
// PWM4P_OUT_EN(); // 开启输出通道
// PWMA_Duty4(0);
// 配置PWM2
PWMA_CC2E_Disable(); // 关闭输入捕获/比较输出
PWMA_CC2NE_Disable(); // 关闭比较输出
PWMA_OC2_ReloadEnable(); // 允许 OC2PE 输出比较的预装载功能
PWMA_CC2S_Direction(CCAS_OUTPUT); // CCnS仅在通道关闭时才是可写的
PWMA_OC2ModeSet(CCMRn_PWM_MODE1); // 设置输出比较模式
PWMA_CC2E_Enable(); // 开启比较输出
PWM2P_OUT_EN(); // 开启输出通道
PWMA_Duty2(0);
// 配置PWMA
PWMA_CCPCAPreloaded(DISABLE);
PWMA_AutoReload(199); // 周期设置 100KHz = 10us
PWMA_BrakeOutputEnable(); // 主输出使能
PWMA_CEN_Enable(); // 使能计数器
EAXRAM();
}
static void timerInit() {
u16 timePreVal = 65536UL - 1000 * (MAIN_Fosc / 1000000UL); // 1ms
TIM_InitTypeDef TIM_InitStructure; // 结构定义
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReloadNoMask; // 16位自动重载,不可屏蔽
TIM_InitStructure.TIM_Interrupt = ENABLE; // 允许中断
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; // 内部时钟1T
TIM_InitStructure.TIM_ClkOut = DISABLE; // 不输出高速脉冲
TIM_InitStructure.TIM_Value = timePreVal; // 设置初值
TIM_InitStructure.TIM_Run = ENABLE; // 启动定时器
Timer_Inilize(Timer0, &TIM_InitStructure); // 初始化Timer0
}
static u16 getNTC();
static u16 getTemp();
static u8 calcPWM(u16 temp);
static void updataPWM(u8 pwmPercent);
void init() {
GPIOInit();
uartInit();
timerInit();
ADCInit();
PWMInit();
// 初始化缓存队列
InitRing(&adcRing);
Delay50ms();
EADC = 1; // 启动ADC中断
EA = 1; // 启动全局中断
}
void core() {
curTemp = getTemp();
curPwm = calcPWM(curTemp);
if (update) { // 每10ms执行一次PWM更新
updataPWM(curPwm);
}
if (tick) { // 每一秒执行一次状态报告
char string[30] = {0};
sprintf(string, "temp: %3dC, pwm: %3d%%\r\n", curTemp, curPwm);
PrintString1(string);
tick = FALSE;
}
}
/**
* 1024 / (4700 + R) = ADC / R
* => R = (4700 * ADC) / (1024 - ADC)
*
* NTC100K 单位是 10 Ω
* return (R / 10)
*/
static u16 getNTC() {
if (adcRing.full) {
u8 i;
u16 max = 0, min = 1024;
u16 sum = 0, raw = 0, avg = 0, res = 0;
EA = 0;
memcpy(ntcAdcBuf, adcRing.buf, sizeof(ntcAdcBuf));
EA = 1;
for (i = 0; i < ADC_BUF_LENGTH; i++) {
raw = ntcAdcBuf[i];
sum += raw;
if (raw > max) max = raw;
if (raw < min) min = raw;
}
sum = sum - min - max;
avg = sum / (ADC_BUF_LENGTH - 2);
res = (47 * avg) / (1024 - avg);
if (res > 6553)
return 0xFFFF;
else
return res * 10;
} else {
return 0xFFFF;
}
}
/**
* 获取当前温度
* 阻值表的索引值即是温度值
*/
static u16 getTemp() {
u16 i, raw = getNTC();
for (i = 0; i < sizeof(NTC100K); i++) {
if (raw >= NTC100K[i]) break;
}
return i;
}
/**
* 根据输入的温度计算PWM百分比
* TODO 串口输入调整对应参数
*
* 最小启动风扇百分比 默认20%
* 风扇启动温度 默认35C
* 风扇最大温度 默认65C
*/
static u8 calcPWM(u16 temp) {
if (temp < 35) {
return 0;
} else if (temp > 65) {
return 100;
} else {
return 20 + (temp - 35) * (100 - 20) / (65 - 35);
}
}
/**
* 更新PWM占空比, 输入百分比
*/
static void updataPWM(u8 pwmPercent) {
u16 duty;
if (pwmPercent > 100) pwmPercent = 100;
duty = pwmPercent * (PWM_ARR + 1) / 100;
EAXSFR();
PWMA_Duty2(duty);
EAXRAM();
}
/**
* Timer0中断
*/
void timer0_ISR(void) interrupt TIMER0_VECTOR {
ADC_START_NTC; // 每1ms启动一次ADC转换
sysTime++;
if (sysTime % 10 == 0) {
update = TRUE;
if (sysTime % 1000 == 0) {
tick = TRUE;
}
}
}
/**
* ADC中断
*/
void ADC_ISR() interrupt ADC_VECTOR {
ADC_CONTR &= ~ADC_FLAG;
SaveRing(&adcRing, ((u16)ADC_RES << 8) | ADC_RESL);
}
/**
* PWM中断
*/
void PWMA_ISR() interrupt PWMA_VECTOR {
// if (PWMA_SR1 & UIF1) {
// PWMA_SR1 &= ~UIF1;
// }
// if (PWMA_SR1 & CC4IF) {
// // if (num++ == 72) {
// // num--;
// // EAXSFR();
// // PWMA_CCR4 = 0;
// // EAXRAM();
// // PWMA_SR1 &= ~CC4IF;
// // } else {
// // v_led = *p_led;
// // switch (b_num++) {
// // case 0: b_led = v_led & 0x80; break;
// // case 1: b_led = v_led & 0x40; break;
// // case 2: b_led = v_led & 0x20; break;
// // case 3: b_led = v_led & 0x10; break;
// // case 4: b_led = v_led & 0x08; break;
// // case 5: b_led = v_led & 0x04; break;
// // case 6: b_led = v_led & 0x02; break;
// // case 7: b_led = v_led & 0x01;
// // default:
// // b_num = 0;
// // p_led++;
// // break;
// // }
// // EAXSFR();
// // if (b_led)
// // PWMA_CCR4 = 16;
// // else
// // PWMA_CCR4 = 8;
// // EAXRAM();
// // PWMA_SR1 &= ~CC4IF;
// // }
// }
}