はじめに
前回の記事では、ポーリングによるDMX受信を行いました。
しかし、1ch目はしっかりと受信できていたにも関わらず、
2ch目以降は安定した受信ができていませんでした。
今回はUSART割り込みによる受信を
行い、うまく受信できましたので、
動画も交えて紹介していきます。
今回の回路

前回と全く同様の回路です。
実際のコード
コードも基本的にはDMX受信部分だけを
割り込みにしただけで、それ以外はほぼ前回と同じです。
void Pin_Init(void) {
ANSELA = 0x00;
ANSELB = 0x00;
TRISAbits.TRISA2 = 0;
TRISAbits.TRISA1 = 0;
LATAbits.LATA2 = 0;
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
PIE1bits.RCIE = 1; //追加
INTCONbits.PEIE = 1; //追加
INTCONbits.GIE = 1; //追加
}
void PWM_Init(void) {
OSCCON = 0b01110010; //8MHz
TRISCbits.TRISC2 = 0; //CCP1 OUT
TRISCbits.TRISC1 = 0; //CCP2 OUT
TRISBbits.TRISB5 = 0; //CCP3 OUT
TRISBbits.TRISB0 = 0; //CCP4 OUT
ANSELB = 0x00; //RBxbits digital
APFCONbits.CCP2SEL = 0; //0:RC1, 1:RB3
APFCONbits.CCP3SEL = 1; //0:RC6, 1:RB5
T2CONbits.T2CKPS = 0b10; //prescaler 1:16
T2CONbits.TMR2ON = 1; //Timer2 ON
PR2 = 124; // 1kHz
CCP1CON = 0b00001100; //CCP1 PWM mode
CCP2CON = 0b00001100; //CCP2 PWM mode
CCP3CON = 0b00001100; //CCP3 PWM mode
CCP4CON = 0b00001100; //CCP4 PWM mode
}
void pwm_apply(unsigned char i, unsigned char data) {
unsigned int duty;
duty = ((unsigned int) data << 1) - (data >> 5);
if (duty >= 500) {
duty = 499;
}
switch (i) {
case 0:
CCPR1L = duty >> 2;
CCP1CONbits.DC1B = duty & 0x03;
break;
case 1:
CCPR2L = duty >> 2;
CCP2CONbits.DC2B = duty & 0x03;
break;
case 2:
CCPR3L = duty >> 2;
CCP3CONbits.DC3B = duty & 0x03;
break;
case 3:
CCPR4L = duty >> 2;
CCP4CONbits.DC4B = duty & 0x03;
break;
}
}
void USART_Init(void) {
TXSTAbits.SYNC = 0;
TXSTAbits.BRGH = 1;
BAUDCONbits.BRG16 = 1;
SPBRG = 7;
SPBRGH = 0;
RCSTAbits.SPEN = 1;
RCSTAbits.CREN = 1;
}
/*****DMX受信の割り込み処理******/
void __interrupt() isr(void) {
if (!PIR1bits.RCIF) {
return;
}
if (RCSTAbits.OERR) {
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
if (RCSTAbits.FERR) {
dummy = RCREG;
dmx_count = 0;
return;
}
unsigned char data = RCREG;
if (dmx_count == 0) {
start_code = data;
} else if ((dmx_count <= 512) && (start_code == 0x00)) {
for (unsigned char i = 0; i < 4; i++) {
if (dmx_count == my_address[i]) {
dimmer[i] = data;
}
}
}
dmx_count++;
}
void main(void) {
Pin_Init();
USART_Init();
PWM_Init();
while (1) {
for (unsigned char i = 0; i < 4; i++) {
pwm_apply(i, dimmer[i]);
}
}
}
前回の記事から変更した点は、
DMX受信をポーリングからUSART割り込みへ
変更したことだけです。
それ以外のPWM処理やDMX解析処理はほぼそのままです。
実際に書き込み動かしてみた様子が、
次の動画です。
ポーリングでは、
メインループでPWM処理などを行っている間に
DMXデータを取りこぼしてしまうことがありました。
一方、USART割り込みでは受信した瞬間に
CPUが受信処理へ移るため、
4chすべてを安定して受信できるようになりました。
考察と次回予告
前回、ポーリングによりDMX信号の受信を試みましたが、
うまく受信しきれませんでした。
そのため、今回は割り込み処理によってDMX信号の受信を行い、
見事にきれいにPWM出力をさせることができました。
次回は、DMX値をそのままPWMへ出力するだけでなく、
LEDが消灯直前でも安定して点灯できるようにする
「下限オフセット機能」
を実装します。
実際の照明器具でも使われる考え方を取り入れ、
より実用的な調光器へ近づけていきます。
シリーズ一覧
STEP1 UART
STEP2 RS485
STEP3 DMX送信
STEP4 DMX理解
STEP5 DMX受信
▶ STEP6 DMX→PWM(今回)
STEP7 現場仕様化


コメント