348 lines
10 KiB
C++
348 lines
10 KiB
C++
/****************************************************************************
|
|
* @file main.c
|
|
* @version V3.0err
|
|
* $Revision: 4 $
|
|
* $Date: 17/05/04 12:57p $
|
|
* @brief Perform A/D Conversion with ADC continuous scan mode.
|
|
* @note
|
|
* Copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
|
|
*
|
|
******************************************************************************/
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include "M0564.h"
|
|
#include "define.h"
|
|
#define INTERRUPT
|
|
// dead time unit = 1/72us
|
|
// ex. dead time 72 = 1us, 36 = 0.5us, 18=0.25us
|
|
#define DEAD_ZONE_01 36 // unit=1/72us, PWM0.0 PWM0.1 Dead time
|
|
#define DEAD_ZONE_23 72 // unit=1/72us, PWM0.2 PWM0.3 Dead time
|
|
#define DEAD_ZONE_45 18 // unit=1/72us, PWM0.4 PWM0.5 Dead time
|
|
|
|
int Sync = 0;
|
|
volatile int Positve = -1, DetectPeriodP, DetectPeriodN;
|
|
int StableCnt;
|
|
volatile int err;
|
|
// phase angle, pwm freq in KHZ
|
|
const unsigned int FREQ_TBL[][2] = {
|
|
{30, 60},
|
|
{50, 80},
|
|
{70, 100},
|
|
{90, 150},
|
|
{110, 150},
|
|
{130, 100},
|
|
{150, 80},
|
|
{180, 60},
|
|
{210, 60},
|
|
{230, 80},
|
|
{250, 100},
|
|
{270, 150},
|
|
{290, 150},
|
|
{310, 100},
|
|
{330, 80},
|
|
{360, 60}};
|
|
unsigned int Period_tbl[361];
|
|
|
|
/**
|
|
* @brief ACMP01 IRQ
|
|
*
|
|
* @param None
|
|
*
|
|
* @return None
|
|
*
|
|
* @details The ACMP01 default IRQ, declared in startup_M0564.s.
|
|
*/
|
|
extern "C" {
|
|
|
|
void ACMP01_IRQHandler(void) {
|
|
|
|
if(ACMP_GET_INT_FLAG(ACMP01, 1)) {
|
|
ACMP_CLR_INT_FLAG(ACMP01, 1); // clear interrupt flag
|
|
int T = TIMER_GetCounter(TIMER0); // get timer0 counter
|
|
if(TIMER0->CTL & TIMER_CTL_CNTEN_Msk) {
|
|
if(T < NOISE) return; // noise. skip
|
|
} else {
|
|
//StableCnt = 0;
|
|
//Positve = -1;
|
|
}
|
|
TIMER_Stop(TIMER0); // stop timer0
|
|
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
|
|
TIMER0->CNT = 0; // set timer0 cnt to 0
|
|
TIMER_Start(TIMER0); // start timer0
|
|
if(HZ_50U < T || T < HZ_60L) { // not in range
|
|
Positve = -1;
|
|
StableCnt = 0;
|
|
err = 1;
|
|
} else {
|
|
if(StableCnt < STABLE_CNT) { // wait until stable
|
|
StableCnt++;
|
|
} else {
|
|
if(ACMP_GET_OUTPUT(ACMP01, 1)) { // N > L
|
|
Positve = 1; // positve
|
|
DetectPeriodN = T; // yes, Save period
|
|
} else { // L <= N
|
|
Positve = 0; // positve
|
|
DetectPeriodP = T; // yes, Save period
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void TMR2_IRQHandler(void) {
|
|
|
|
TIMER_ClearIntFlag(TIMER2); // clear interrupt flag
|
|
PWM_Func();
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
/* Init TABLE */
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
void TABLE_Init() {
|
|
|
|
for(int i = 0, j = 0 ; i < 361 ; i++) {
|
|
if(i > FREQ_TBL[j][0]) {
|
|
j++;
|
|
}
|
|
Period_tbl[i] = (BASE_CLOCK/1000 + (FREQ_TBL[j][1]/2))/FREQ_TBL[j][1] - 1;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
/* WM callback */
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
void PWM_Func() {
|
|
|
|
int currState, T, PeriodN, PeriodP;
|
|
do { // Get Curr State, Period and time
|
|
currState = Positve;
|
|
T = TIMER_GetCounter(TIMER0);
|
|
PeriodN = DetectPeriodN;
|
|
PeriodP = DetectPeriodP;
|
|
} while(currState != Positve); // ACMP interrupt occurs ?
|
|
if(currState < 0) { // Unrecognized signal?
|
|
ComplementaryPWM0(0, 0); // Turn off PWM
|
|
ComplementaryPWM0(2, 0); // Turn off PWM
|
|
ComplementaryPWM0(4, 0); // Turn off PWM
|
|
} else if(TIMER_GetIntFlag(TIMER0)) { // Unrecognized signal?
|
|
Positve = -1;
|
|
StableCnt = 0;
|
|
ComplementaryPWM0(0, 0); // Turn off PWM
|
|
ComplementaryPWM0(2, 0); // Turn off PWM
|
|
ComplementaryPWM0(4, 0); // Turn off PWM
|
|
} else {
|
|
Sync = SYNC_LOST_TIME;
|
|
int Angle;
|
|
if(currState == 0) { // negative wave
|
|
if(T >= PeriodN) { // over 360?
|
|
Angle = 359;
|
|
} else {
|
|
Angle = 180 + 180*T/PeriodN; // calculate angle
|
|
}
|
|
} else {
|
|
if(T >= PeriodP) { // over 180?
|
|
Angle = 179;
|
|
} else {
|
|
Angle = 180*T/PeriodP; // calculate angle
|
|
}
|
|
}
|
|
#ifdef DEBUG_IO
|
|
const int N = 13;
|
|
if(Angle >= FREQ_TBL[N][0] && Angle <= FREQ_TBL[N+1][0]) {
|
|
PC0 = 1;
|
|
} else {
|
|
PC0 = 0;
|
|
} // set output pwm
|
|
#else
|
|
int T = Period_tbl[Angle]; // get output freq
|
|
ComplementaryPWM0(0, T); // output pwm
|
|
ComplementaryPWM0(2, T); // output pwm
|
|
ComplementaryPWM0(4, T); // output pwm
|
|
#endif
|
|
}
|
|
|
|
}
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
/* UART function */
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
void UART_Func() {
|
|
|
|
int P1, P2;
|
|
int Func = UART_Command(P1, P2);
|
|
if(Func) {// command is received?
|
|
switch(Func) {
|
|
case 'v': // read v
|
|
print("%d\r\n", ADC_GET_CONVERSION_DATA(ADC, P1));
|
|
break;
|
|
case 'f': // read f
|
|
case 't': // read t
|
|
break;
|
|
case 'F': // write F
|
|
PWM(P1, P2>>1, P2);
|
|
break;
|
|
case 'T': // write T
|
|
case 'V': // write V
|
|
case 'a': // left
|
|
case 'w': // up
|
|
case 'd': // right
|
|
case 'x': // down
|
|
case ' ': // space
|
|
print("NA\r\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
/* BUTTON function */
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
void BUTTON_Func() {
|
|
|
|
|
|
if(Sync) {
|
|
Sync--;
|
|
}
|
|
static int t;
|
|
if(++t >= BLINK_TIME) {
|
|
t = 0;
|
|
if(Sync) SEG_DP = 0; // if signal is valid, blink DP
|
|
LED = 0;
|
|
if(err) {// if signal is unrecognized, display number counting
|
|
err = 0;
|
|
static unsigned char disp_num;
|
|
if(++disp_num < '0' || disp_num > '9') disp_num = '0';
|
|
Display(disp_num);
|
|
}
|
|
} else {
|
|
SEG_DP = 1;
|
|
LED = 1;
|
|
}
|
|
static unsigned int pressed = 0, deboounce_cnt;
|
|
if(pressed) {
|
|
if(!UP || !DOWN || !LEFT || !RIGHT) { // key is not released
|
|
deboounce_cnt = DEBOUNCE_TIME;
|
|
} else if(--deboounce_cnt == 0) {
|
|
pressed = 0;
|
|
}
|
|
} else if(!UP) {// UP is pressed
|
|
pressed = 1;
|
|
deboounce_cnt = DEBOUNCE_TIME;
|
|
} else if(!DOWN) {// DOWN is pressed
|
|
pressed = 1;
|
|
deboounce_cnt = DEBOUNCE_TIME;
|
|
} else if(!LEFT) {// LEFT is pressed
|
|
pressed = 1;
|
|
deboounce_cnt = DEBOUNCE_TIME;
|
|
} else if(!RIGHT) {// RIGHT is pressed
|
|
pressed = 1;
|
|
deboounce_cnt = DEBOUNCE_TIME;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
/* MAIN function */
|
|
/*---------------------------------------------------------------------------------------------------------*/
|
|
int main(void)
|
|
{
|
|
/* Unlock protected registers */
|
|
SYS_UnlockReg();
|
|
|
|
/* Init System, IP clock and multi-function I/O */
|
|
SYS_Init();
|
|
|
|
/* Lock protected registers */
|
|
SYS_LockReg();
|
|
|
|
/* Init TABLE */
|
|
TABLE_Init();
|
|
|
|
// Display 8
|
|
Display('8');
|
|
|
|
/* Init TIMER0 */
|
|
TIMER0_Init();
|
|
|
|
/* Init TIMER1 */
|
|
TIMER1_Init();
|
|
|
|
/* Set Pwm mode as complementary mode */
|
|
PWM_ENABLE_COMPLEMENTARY_MODE(PWM0);
|
|
|
|
// Initial PWM
|
|
PWM_Init();
|
|
|
|
// Set PWM0.0 PWM0.1 Dead time
|
|
SetPWM0DeadZone(0, DEAD_ZONE_01);
|
|
// Set PWM0.2 PWM0.3 Dead time
|
|
SetPWM0DeadZone(2, DEAD_ZONE_23);
|
|
// Set PWM0.4 PWM0.5 Dead time
|
|
SetPWM0DeadZone(4, DEAD_ZONE_45);
|
|
|
|
// Initial ADC
|
|
ADC_Init();
|
|
|
|
/* Init UART1 */
|
|
UART1_Init();
|
|
|
|
// Delay 0.5 sec
|
|
TIMER1_Delay(500000);
|
|
|
|
// Display 0
|
|
Display('0');
|
|
|
|
/* Init ACMP */
|
|
ACMP_Init();
|
|
|
|
/* Enable ACMP01 interrupt */
|
|
NVIC_EnableIRQ(ACMP01_IRQn);
|
|
|
|
#ifdef INTERRUPT
|
|
/* Init TIMER2 */
|
|
TIMER2_Init();
|
|
#endif
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
|
|
#ifndef INTERRUPT
|
|
PWM_Func();
|
|
#endif
|
|
UART_Func();
|
|
|
|
if(TIMER_GetIntFlag(TIMER1)) { // timer1 elapsed?
|
|
TIMER_ClearIntFlag(TIMER1); // clear timer1 flags
|
|
BUTTON_Func();
|
|
|
|
int S = CHECK_SHUTDOWN();
|
|
if(S >= 0) {
|
|
if(S) {
|
|
/* Enable TIMER2 interrupt */
|
|
NVIC_DisableIRQ(TMR2_IRQn);
|
|
TIMER_ClearIntFlag(TIMER2);
|
|
|
|
NVIC_DisableIRQ(ACMP01_IRQn);
|
|
TIMER_Stop(TIMER0); // stop timer0
|
|
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
|
|
Positve = -1;
|
|
StableCnt = 0;
|
|
ComplementaryPWM0(0, 0); // Turn off PWM
|
|
ComplementaryPWM0(2, 0); // Turn off PWM
|
|
ComplementaryPWM0(4, 0); // Turn off PWM
|
|
|
|
Display('E');
|
|
} else {
|
|
Display('0');
|
|
TIMER_Stop(TIMER0); // stop timer0
|
|
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
|
|
NVIC_EnableIRQ(ACMP01_IRQn);
|
|
|
|
TIMER_ClearIntFlag(TIMER2);
|
|
/* Enable TIMER2 interrupt */
|
|
NVIC_EnableIRQ(TMR2_IRQn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
|
|
|