I have a question, when I do a compare match in TC.RA, I set the RA register value to a sine function instead of a fixed value, will it be successfully compare matched?
#define LED_PIN 13//割り込み確認用
#include <math.h> // 数学関数用ヘッダ
#define PI 3.1415
#define sinsize (256)
int sinwave_u = 0, sinwave_v = 0, sinwave_w = 0;
/*配列に格納*/
float a[200];//u相
float b[200];//v相
float c[200];//w相
float sinwave[200];
int n=0;
int p=0;
int x = 0, y=0, z=0, w=0, j=0, l=0,o=0;
int q = 0;
float t = 0,t1 = 0;
float sintime = 0;
float average = 0 ;
float average1 = 0 ;
/*1相目(u相)の値A0ピン*/
float value1 = 0;
float volt1 = 0;
float current1 = 0;
/*2相目(v相)の値A1ピン*/
float value2 = 0;
float volt2 = 0;
float current2 = 0;
/*3相目(w相)の値A2ピン*/
float value3 = 0;
float volt3 = 0;
float current3 = 0;
void setup(){
Serial.begin(115200);
tc_setup();
adc_setup();
pwm_setup();
pinMode(LED_PIN,OUTPUT);
}
//TC_はタイマカウンターの構造体
//PMCは電源管理コントローラの構造体
//PIO_は並列入出力コントローラの構造体
/************* Timer Counter 0 Channel 2 to generate PWM pulses thru TIOA2 ************/
void tc_setup() {
PMC->PMC_PCER0 |= PMC_PCER0_PID27; //TC0 power ON : Timer Counter 0 channel 2 IS TC0 p.31 ペリフェラルクロックイネーブルレジスタ0
PMC->PMC_PCER0 |= PMC_PCER0_PID28; //TC1 "|="は論理和 HIGHにしたい時に使う PID28に対応するビットをHIGHにする
PMC->PMC_PCER0 |= PMC_PCER0_PID29; //TC2
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // チャネル制御レジスタ,カウンタークロックイネーブル
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;
TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;
PIOB->PIO_PDR |= PIO_PDR_P25; // PB25 is no more driven by the GPIO p858 インプット/アウトプットライン
//PIOB->PIO_PER |= PIO_PER_P25;
PIOB->PIO_OER |= PIO_OER_P25;
PIOB->PIO_ABSR |= PIO_PB25B_TIOA0; //ピンをペリフェラル機能に割り当てるには,PIO_PDR の書き込みに加えて,ペリフェラル選択レジスタ(PIO_ABSR ABSR)の書き込みが必要
TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // MCK/2, clk on rising edge
| TC_CMR_WAVE // Waveform mode
| TC_CMR_WAVSEL_UPDOWN // UP mode with automatic trigger on RC Compare
| TC_CMR_ACPA_CLEAR // Clear TIOA0 on RA compare match
| TC_CMR_ACPC_SET; // Set TIOA0 on RC compare match
TC0->TC_CHANNEL[0].TC_RC = 28000; //<********************* Frequency = (Mck/2)/TC_RC Hz = 15 KHz
TC0->TC_CHANNEL[0].TC_RA = sinwave_u; //<******************** Duty cycle = (TC_RA/TC_RC) * 100 % = 80 %
uint32_t status;
status = TC0->TC_CHANNEL[0].TC_SR; // Read and clear TC0 status register
status & TC_SR_CPAS;
/*
TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS // Interrupt on RC compare match
| TC_IER_CPAS; // Interrupt on RA compare match
NVIC_EnableIRQ(TC0_IRQn); // Interrupt enable
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable*/
}
void TC0_Handler()
{
uint32_t status;
status = TC0->TC_CHANNEL[0].TC_SR; // Read and clear TC0 status register
if(status & TC_SR_CPAS) {
// Toggle pin 1
}
else if(status & TC_SR_CPCS)
{
// Toggle pin 2
}
}
void adc_setup() {
pmc_set_writeprotect(false); // PMC controller write protection disable.
//PMC->PMC_PCER1 |= PMC_PCER1_PID37; // ADC power on
//ADC->ADC_CR = ADC_CR_SWRST; // Reset ADC
ADC->ADC_MR = ADC_MR_TRGEN_EN // Hardware trigger select
| ADC_MR_TRGSEL_ADC_TRIG5 // Trigger by PWM Event Line 1 PWMイベントライン1をトリガに設定
| ADC_MR_PRESCAL(1); // ここは0でも1でもどっちでも
ADC->ADC_CHER = ADC_CHER_CH7 | ADC_CHER_CH6 | ADC_CHER_CH5; // Enable Channel 7
//NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt
//ADC->ADC_IER = ADC_IER_EOC7; // End Of Conversion interrupt enable for channel 7
}
void pwm_setup(){
REG_PMC_PCER1 |= PMC_PCER1_PID36; // ペリフェラルクロックイネーブルレジスタ1
uint16_t CounterPeriod;
uint16_t DeadTime;
//キャリア周波数10Hz、デッドタイム約1.2usの場合の設定
REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1); // PWMクロックレートを84MHzに設定 (84MHz/1)
CounterPeriod = 8400; //84MHz/5KHz = 16800
DeadTime = 100;
REG_PWM_CPRD0 = CounterPeriod; //CPRDは三角波のトップ
/*
TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // MCK/2, clk on rising edge
| TC_CMR_WAVE // Waveform mode
| TC_CMR_WAVSEL_UP_RC // UP mode with automatic trigger on RC Compare
| TC_CMR_ACPA_CLEAR // Clear TIOA0 on RA compare match
| TC_CMR_ACPC_SET // Set TIOA0 on RC compare match
| TC_CMR_EEVT_XC0 ;
TC0->TC_CHANNEL[2].TC_RC = 14; //<********************* Frequency = (Mck/8)/TC_RC = 44.1 MHz
TC0->TC_CHANNEL[2].TC_RA = 7; //<******************** Any Duty cycle in between 1 and TC_RC
TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC2 counter and enable
*/
REG_PWM_CMR0 = PWM_CMR_CALG | PWM_CMR_CPRE_MCK; //CALG senter Alg
REG_PWM_CMR1 = PWM_CMR_DTE | PWM_CMR_CALG | PWM_CMR_CPRE_MCK;
REG_PWM_CMR2 = PWM_CMR_DTE | PWM_CMR_CALG | PWM_CMR_CPRE_MCK;
REG_PWM_CMR3 = PWM_CMR_DTE | PWM_CMR_CALG | PWM_CMR_CPRE_MCK;
REG_PWM_DT1 = PWM_DT_DTH(DeadTime) | PWM_DT_DTL(DeadTime);
REG_PWM_DT2 = PWM_DT_DTH(DeadTime) | PWM_DT_DTL(DeadTime);
REG_PWM_DT3 = PWM_DT_DTH(DeadTime) | PWM_DT_DTL(DeadTime);
//AD変換のためのPWMイベントライン設定
PWM->PWM_CMP[0].PWM_CMPM = PWM_CMPM_CEN; // PWM0の比較を有効化
PWM->PWM_ELMR[1] = PWM_ELMR_CSEL0; // PWMイベントライン1にPWM0を設定
PWM->PWM_CMP[0].PWM_CMPV = PWM_CMPV_CV(CounterPeriod - 10); // PWM0のDUTYを設定
NVIC_EnableIRQ(TC0_IRQn); // TC2 NVIC enable
NVIC_SetPriority(PWM_IRQn, 0); // PWMコントローラのNVIC(Nested Vector Interrupt Controller)の優先度を0(最高)にする
NVIC_EnableIRQ(PWM_IRQn); // PWMコントローラをNested Vector Interrupt Controller (NVIC)に接続する。
PWM->PWM_ENA |= PWM_ENA_CHID0 | PWM_ENA_CHID0; // PWMチャンネルを有効にする
PWM->PWM_IER1 |= PWM_IER1_CHID0; // イベント割り込みを有効にする
REG_PWM_IER1 = PWM_IER1_CHID0; // Interrupt on PWM Channel 0 counter
// PWM0~3の開始
REG_PWM_ENA = PWM_ENA_CHID3 | PWM_ENA_CHID2 | PWM_ENA_CHID1 | PWM_ENA_CHID0;
}
void loop(){
sinwave_u = (14000 * sin( sintime * 1110*3.14 ) + 14000) ;
sinwave_v = (14000 * sin( sintime * 2 * PI * 60 + (2*3.1415/3) ) + 14000);
sinwave_w = (14000 * sin( sintime * 2 * PI * 60 + (4*3.1415/3) ) + 14000);
TC0->TC_CHANNEL[0].TC_RA = sinwave_u;
if(x==2199){
for(int u=0 ;u>=0 && u<=199;u=u+1){
Serial.print("U相電流 : ");
Serial.println(a[u]);
}
for(int v=0 ;v>=0 && v<=199;v=v+1){
Serial.print("V相電流 : ");
Serial.println(b[v]);
}
for(int w=0 ;w>=0 && w<=199;w=w+1){
Serial.print("W相電流 : ");
Serial.println(c[w]);
}
}
Serial.println(TC0->TC_CHANNEL[0].TC_RA);
}
void PWM_Handler(){
if (REG_PWM_ISR1 & PWM_ISR1_CHID0) // Check if an update condition has occured
{
ADC_Handler();
}
}
void ADC_Handler(){
value1 = ADC->ADC_CDR[7];
value2 = ADC->ADC_CDR[6];
value3 = ADC->ADC_CDR[5];
//電流センサ計算部分//
volt1 = ((value1-17)*(3.3/ 4095.0)) ;
volt2 = ((value2-17)*(3.3/ 4095.0)) ;
volt3 = ((value3-17)*(3.3/ 4095.0)) ;
current1 = ((volt1 - 2.5)*40) ;
current2 = ((volt2 - 2.5)*40) ;
current3 = ((volt3 - 2.5)*40) ;
//配列に値を格納//
x++;
if(2000<=x && x<=2199){
//A/D変換の値を格納//
a[y] = value1;
b[z] = value2;
c[j] = value3;
//電流値を格納//
/* a[y] = current1;
b[z] = current2;
c[w] = current3;*/
l++;
y++;
z++;
j++;
}
//サイン関数の値の更新
t = t + 2;
sintime = (t / 10e6);
//PIOB->PIO_ODSR ^= PIO_ODSR_P27; //割り込み確認用
if(n%2==0){
digitalWrite(LED_PIN,HIGH);
n++;
}
else{
digitalWrite(LED_PIN,LOW);
n++;
}
}