- #include "Mini5D_BLDC_V16.h"
- #include "Mini5D_BLDC.h"
- uint32_t volatile Duty_Command ; // 调速旋钮要求的占空比,范围 0 ~ CNR
- uint32_t volatile Pulse_Current ; // PPM 当前值,P3.6中断代码里得到这个值
- uint32_t volatile PulseTick ; // PPM 上沿时刻
- uint32_t Pulse_Min = 1000 ; // PPM 最小值,缺省1000us
- uint32_t Pulse_Length = 1000 ; // PPM 最大值与最小值的差
- ////=====================================================================================
- ////UART0 Initial ///////////////////////////////////////////////////////////////////////
- void UART0_Init(uint32_t Baud)
- {
- UART0->FUN_SEL = 0 ; //UART 模式
- UART0->LCR = 0x0007 ; //8bit, 2-stop, no parity
- UART0->BAUD = 0x30000000 + 22118400/Baud - 2 ; //UART 时钟 22M
- UART0->FCR = 0x00020020 ; //RTS trigger:8, FIFO trigger:8 BYTE
- UART0->IER = 0 ;
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- // Configure P2.23456 & P0.4 as PWM function pin. configure P1.0345 as ACMP input pin
- void GPIO_Init(void)
- { // P01配置成OUT模式,才能由PHCHG控制,QB模式不行
- // P0.014567六个, DOUT的初值在函数PWM_ACMP0_T0_T1_Init()中配置
- GPIO0->PMD = Px7_QB | Px6_QB | Px5_QB | Px1_OUT | Px0_OUT ; // P0.1 可以为 A-
- GCR->P0_MFP = 0xF010 ; // P0.4_PWM5, P0.0567_SPI
-
- GPIO1->DOUT = 0 ;
- GPIO1->PMD = Px5_OUT | Px4_OUT |Px3_OUT | Px2_OUT | Px0_OUT ; // P1.02345 五个
- GPIO1->OFFD = 0x00FF0000 ; // 数字输入通道全关闭
- GCR->P1_MFP = 0x303D ; // P1.023_ADC123, P1.45_ACMP0
- // GPIO2->DOUT 的初值在函数PWM_ACMP0_T0_T1_Init()中配置
- GPIO2->PMD = Px6_OUT | Px5_OUT | Px4_OUT | Px3_OUT | Px2_OUT ;
- GCR->P2_MFP = 0x7C00 ; // P2.23456,五个,PWM01234
- GPIO3->DOUT = 0xFF ; // P3.012456 六个
- GPIO3->OFFD = 0x00BF0000 ; // 只接通36的数字输入通道
- GPIO3->PMD = Px6_QB ; // P3.0245_CMP1,P3.6_T1EX,P3.1_ADC7
- GCR->P3_MFP = 0x01003376 ;
- GPIO4->DOUT = 0xFF ;
- GPIO4->PMD = Px7_QB | Px6_QB ; // P4.67,ICE接口
- GCR->P4_MFP = 0 ;
- GPIO5->DOUT = 0xFF ; // P5.012345 六个,(QFN33没有P5.5)
- GPIO5->PMD = Px5_QB | Px4_QB | Px2_QB | Px1_QB | Px0_QB ;
- GCR->P5_MFP = 0x0008 ; // P5.3_ADC0
-
- GPIO3->ISR = 0xFF ; // Clear ISR
- GPIO3->IMD = 0 ; // Edge interrupt mode
- GPIO3->IER = 0x00400040 ; // 位16~23上沿使能,0~7下沿中断使能
- GPIO3->DBEN = 0x40 ; // 1 mean De-bounce
- GPIODBNCE = 0x2B ; // De-bounce time = 2048HCLK
- NVIC_SetPriority(GPIO234_IRQn, 2); // Interrupt priority = 2
- NVIC->ISER[0] = 1<<GPIO234_IRQn ;
-
- GPIO5->ISR = 0xFF ; // Clear ISR
- GPIO5->IMD = 0 ; // Edge interrupt mode
- GPIO5->IER = 0x00000004 ; // 位16~23上沿使能,0~7下沿中断使能
- GPIO5->DBEN = 0x04 ; // P5.2 Enable De-bounce
- NVIC_SetPriority(EINT1_IRQn, 2) ; // Interrupt priority = 2
- // NVIC->ISER[0] = 1<<EINT1_IRQn ; // 按键
- }
- //=======================================================================================
- // MAIN function
- //---------------------------------------------------------------------------------------
- int main(void)
- {
- uint32_t Adc_Vin, Adc_Tempera, temp32, LastDuty = ~0 ;
-
- PWM_ACMP0_T0_T1_Init() ;
- ADC->CR = ADCR_EN ; // 尽早使能ADC,需100us稳定
- ADC->ADSAMP = 4 ; // 采样时间 1+8CLK
- ADC->ADTDCR = 0 ;
- //PWM频率: 5=22.1KHz, 6=18.4KHz, 7=15.8KHz, 8=13.8KHz, 10=11KHz, 14=7.9K
- PWM_one_percent = 10 ;
- PWM->CNR0 = 100*PWM_one_percent - 1 ; // 设置 PWM 周期, PWM 时钟 11.0592MHz
- PWM->CNR1 = 100*PWM_one_percent - 1 ;
- Duty_Min = 9*PWM_one_percent ; // 电压小于Duty_Min停转
-
- // UART0_Init(115200) ;
- GPIO_Init() ;
- // 检测 BOD 电压是否配置为 3.7V 以下保持复位 //////////////////////////////////////////
- CLK->AHBCLK |= CLK_ISP_EN ;
- FMC->ISPCON |= FMC_CFGUEN | FMC_EN_ ;
- FMC->ISPADR = 0x00300000 ; // Config0
- FMC->ISPCMD = FMC_READ_0 ; // Read config0
- FMC->ISPTRG = 1 ;
- while(FMC->ISPTRG & 1) ;
- temp32 = FMC->ISPDAT ;
- if((temp32 & 0x00F004C1) != 0x00400481){
- FMC->ISPCMD = FMC_ERASE ;
- FMC->ISPTRG = 1 ;
- while(FMC->ISPTRG & 1) ;
- FMC->ISPDAT = (temp32 & 0xFF0FFF3F) | 0x00400481 ; // 把 BOD 电压写成 3.7V 以下复位
- FMC->ISPCMD = FMC_WRITE ;
- FMC->ISPTRG = 1 ;
- while(FMC->ISPTRG & 1) ;
- GCR->IPRST_CTL1 = 1 ; // 芯片复位
- }
- FMC->ISPCON &= ~(FMC_CFGUEN | FMC_EN_) ;
- CLK->AHBCLK &= ~CLK_ISP_EN ;
- LOCKREG();
- ///////////////////////////////////////////////////////////////////////////////////////
- gFlag = 0 ; // 清0标志
- ACMP_Flag = 0 ;
- TIMER1->EXCON = TEX_DEBO_EN |TEX_EN | TEX_CAP_FALL_RISE; // 开始捕获速度脉冲
- Duty_Current = 15*PWM_one_percent ;
- Motor_Beep(50*1000,900) ; ++pPhase ; // AB 蜂鸣 50ms
- Motor_Beep(50*1000,800) ; // AC 蜂鸣
- if(Pulse_Current > 1600){ // 一上电 >60% 认为推杆已推到最高
- Pulse_Length = Pulse_Current ;
- while(Pulse_Current > 1400) ; // 等推杆到40%以下
- Delayus(500*1000) ; // 再等半秒
- Motor_Beep(50*1000,900) ;
- Pulse_Min = Pulse_Current ;
- Pulse_Length = Pulse_Length - Pulse_Min - 50 ; // 推杆最大值减最小值
- Motor_Beep(50000,800) ;
- }
- Pulse_Length = ((100*PWM_one_percent)<<16)/Pulse_Length; // 得到 PPM 校正系数
- Motor_Beep(50000,600) ;
- ///////////////////////////////////////////////////////////////////////////////////////
- ADC->SR |= ADSR_ADF ;
- NVIC_SetPriority(ADC_IRQn, 0) ; // 最高优先级, 及时处理过流情况
- NVIC->ISER[0] = 1 << ADC_IRQn ;
- ADC->CR |= ADCR_PWM_TRG | ADCR_TRG_EN ; // 启动ADC,若要ADC限流功能要使能ADC中断
- while(1){
- //// 测旋钮,温度,电压,电流 ==========================================================
- temp32 = ADC->DR ;
- if(temp32 & 0x20000){ // ADC数据有效,读清0,防真打开ADC寄存器窗时,可能会被防真器清0
- temp32 &= 0x03FF ;
- switch(ADC->CHER & 0xFF){
- case ADC2_VIN :
- Adc_Vin = (Adc_Vin + temp32) >> 1 ; // 相当于低通滤波器
- ADC->CHER = ADC3_TEMP ;
- break ;
-
- case ADC3_TEMP :
- Adc_Tempera = (Adc_Tempera + temp32) >> 1 ;
-
- default :
- ADC->CHER = ADC2_VIN ;
- }
- }
- ////=================================================================================
- if(gFlag & Flag_PPM_OK){ gFlag &= ~Flag_PPM_OK ; // 有PPM信号, 更新占空比
- if(Pulse_Current <= Pulse_Min) Duty_Command = 0 ;
- else Duty_Command=((Pulse_Current - Pulse_Min)*Pulse_Length)>>16; // 变到 0 ~ CNR0左右
- Duty_Target = Duty_Command ;
- }
- else{
- temp32 = PulseTick ;
- if(((TIMER1->DR - temp32)&0xFFFFFF) > 3000*1000){ // 3 秒无 PPM 调速信号
- PulseTick = TIMER1->DR ;
- Duty_Target = (Duty_Target*7) >> 3 ; // 目标占空比降为 87.5%
- }
- }
- Duty_Target = 20*PWM_one_percent ; // 用于测试
-
- if((LastDuty ==0)&&(Duty_Target)){ // 突然加电
- if(PeriodNow > 3000) BLDC_Start(PeriodMax, 0); // 快速调整速度
- if(Duty_Current < Duty_Min) Duty_Current = Duty_Min ;
- }
- LastDuty = Duty_Target ;
-
- BLDC_Control() ; // BLDC监控函数: 控制BLDC的启转、停转, 并调整输出电压、导通角、输出方式
- ////===== 其它任务放此 ==============================================================
- }
- }
- void GPIO234_IRQHandler(void) // 调速脉宽测量
- {
- uint32_t temp32 ;
-
- // if(GPIO3->ISR & 0x40){ // GPIO234无其它中断,此句略
- if(GPIO3->PIN & 0x40) PulseTick = TIMER1->CAP ; // PPM 上沿时刻
- else{
- temp32 = ((TIMER1->CAP - PulseTick)&0xFFFFFF) ; // PPM 宽度,微秒数
- if(temp32 < 2500){Pulse_Current = temp32; gFlag |= Flag_PPM_OK; }
- }
- TIMER1->EXISR = ~0 ; // 清中断标志
- // } // End of "if(GPIO3->ISR & 0x40)"
- GPIO3->ISR = ~0 ; // 清中断标志
- }
- void SysTick_Handler(void) // 100ms 中断一次
- {
- ++TickRelay ;
- #if 0 // 打印速度信息
- {
- uint32_t static Cnt = 0, flag = 0 ;
- uint8_t str[] = "Duty= % rpm\n\r" ;
-
- if(++Cnt >= 5){ Cnt = 0 ; flag ^= 1 ; // 0.1s X 5 =0.5S
- if(flag == 0){
- HexToStr(60000000/PeriodAvg, &str[16]) ; // 转速转换成字符
- Tx0FillFiFo(&str[10],13) ; // Tx0 写入 13 个字符
- }
- else{
- HexToStr(PWM->CMR0/PWM_one_percent, &str[7]) ; // 占空比转换成字符
- Tx0FillFiFo(str,10) ; // Tx0 写入 10 个字符
- }
- }
- }
- #endif
- }