/* * main.c * * Created on: 2023年7月4日 * Author: User */ #include "main.h" #include #include #include #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; // // } // } }