#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
}