Building a PIC based DMX Dimmer - Problems - Page 1
Forum section: electronics / general

author: kolbep
author_rank: Frequent Contributor
timestamp: August 09, 2014, 09:24:22 pm
content: Good day all.I am trying to build a DMX-512 receiver.I am testing it using a DMXCreator USB Dongle that is working, as it runs other lighting.I have the dongle connected directly to my Max485 chip, without any thing else on the bus.I am using a PIC18F2420 uC, with a MAX485 Transceiver connected to the USART RX pin (RC7).I have read AP1076, but prefer to code in C18.I have taken the code from :http://dbprototyping.com/dmxTXRX.htmThis code is for the 18f46k20, which they operate at 16Mhz. My pic is set to operate at 8Mhz which is it's maximum,I have taken their code, and changed some of the config settings that were not compatible with my Pic. I have also recalculated the SPBRG to be 7 (instead of the 15 they used).But the problem is that I am not seeing the Framing error.If you see, I have put XLCD writes to help with my debugging, and it gets to the point where it writes a 3, then because FRAME_ERROR==0, it loops back using the goto WaitBreak step.Please, any suggestions why it would not see the Framing Error (Even if I take that PIC pin high or low with a jumper, it does not even generate the error. Suggestions would be welcome. My code is below. Thanks :Code:/** File: DMXRecv.c* Author: Peter** Created on 09 August 2014, 17:26*//** C O N F I G U R A T I O N B I T S ******************************/#pragma config OSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H#pragma config PWRT = OFF, BOREN = OFF //,BORV = 30 // CONFIG2L#pragma config WDT = OFF, WDTPS = 32768 // CONFIG2H#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTB // CONFIG3H#pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L#pragma config CP0 = OFF, CP1 = OFF //, CP2 = OFF, CP3 = OFF // CONFIG5L#pragma config CPB = OFF, CPD = OFF // CONFIG5H#pragma config WRT0 = OFF, WRT1 = OFF//, WRT2 = OFF, WRT3 = OFF // CONFIG6L#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H#pragma config EBTR0 = OFF, EBTR1 = OFF//, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L#pragma config EBTRB = OFF // CONFIG7H/** I N C L U D E S **************************************************/#include <timers.h>#include <string.h>#include <usart.h>#include <pwm.h>#include <stdio.h>#include <stdlib.h>#include <delays.h>#include "xlcd.h"/***//** PROTOTYPES *****************************************************/void setup_usart(void);// setup baud rate etc. of USARTvoid setup_pwm(void);// setup pwm etc/* declare statically allocated uinitialized variables *********/#pragma udatachar RXbuffer;char DataVal = 0;intslot = 0;int channel = 1;/* Declare executable instructions ****************************///#pragma code// Delays for XLCD.hvoid DelayFor18TCY( void ) { Delay10TCYx(2); }void DelayPORXLCD( void ) { Delay1KTCYx(10); }void DelayXLCD( void ) { Delay10TCYx(5); }void main(void) {// set internal oscillator to 16MHzOSCCON = 0x70;// IRCFx = 111OSCTUNEbits.PLLEN = 0;// x4 PLL disabledLATA=0x00;LATB=0x00;LATC=0x00;TRISA=0x00;TRISB=0x00;TRISC=0xFF;//INITIALISE THE LCDwhile( BusyXLCD() );OpenXLCD( FOUR_BIT & LINES_5X7);WriteCmdXLCD( BLINK_OFF & CURSOR_OFF);WriteCmdXLCD( SHIFT_DISP_LEFT );while ( BusyXLCD());//BANNERputrsXLCD("DMX Buddy v1.0");// ########## NOW THE DMX ROUTINESmemset(RXbuffer, 0, 128);// clear RXbuffersetup_usart();// setup USART//setup_pwm();// setup PWM & timer2while(1){/*Synchronise with the transmitter - wait fro break*/WaitBreak:WriteCmdXLCD ((0x80+0x39)); //Line 2putrsXLCD("1 ");if (DataRdyUSART()) { ReadUSART(); }// if byte received correctly discard itputrsXLCD("2 ");if (USART_Status.FRAME_ERROR == 0)// wait for framing error{ putrsXLCD("3 ");goto WaitBreak; }// loop till framing error detectedputrsXLCD("4 ");ReadUSART();// read USART to clear error/* Wait for the START code */putrsXLCD("5 ");WaitStart:while(!DataRdyUSART());// wait until byte receivedputrsXLCD("6 ");if(USART_Status.FRAME_ERROR == 1)// if framing error wait start{goto WaitStart;}WriteCmdXLCD ((0x80+0x49));putrsXLCD("RD ");if (ReadUSART() != 0) goto WaitBreak;// read the data & check if 0/* Receive 512 bytes of data*/for (slot=0; slot<128; slot++){if (RCSTAbits.FERR == 1) break;// check for framing errorwhile (!DataRdyUSART());// wait for data to be available// LATCbits.LATC4=0;RXbuffer = ReadUSART();// read and copy data to RXbuffer//LATCbits.LATC4=1;}/* When frame complete use selected channel to control PWM duty cycle *///CCPR1L = RXbuffer;// get value and set PWM duty cycle// Output the string a character at a time//WriteCmdXLCD ((0x80+0x4C));//putrsXLCD("Egg");// if (CCPR1L>=128) { putrsXLCD(">128"); };// if (CCPR1L<=128) { putrsXLCD("<128"); };//putrsXLCD("Egg");//}// itoa((RXbuffer),cvalue);//End of Line 2// putrsXLCD(cvalue);}}void setup_usart(void)// Set USART to transmit @ 250KB{OpenUSART( USART_TX_INT_OFF &// disable TX interruptUSART_RX_INT_OFF &// enable RX interruptUSART_ASYNCH_MODE &// set asynchronous modeUSART_EIGHT_BIT &// set 9-bit data modeUSART_CONT_RX &// set port continues RXUSART_BRGH_HIGH, 7);// uses high speed formula, 250KBdBAUDCONbits.BRG16 = 1;// set 16 bit async mode}void setup_pwm(void)// setup PWM etc{OpenTimer2( TIMER_INT_OFF & T2_PS_1_1);// enable timer 2, prescaler = 1:1OpenPWM2(255);// PR2 = 249 Timer 2 Period Register//SetOutputPWM2( FULL_OUT_FWD, PWM_MODE_1 );// CCP1CON = 0b01001100SetDCPWM2(2);}

author: kolbep
author_rank: Frequent Contributor
timestamp: August 10, 2014, 09:29:03 am
content: Bump...

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 10, 2014, 10:07:06 am
content: Have you verified that the UART is running at the right rate, by sending bytes and checking on a scope?

author: kolbep
author_rank: Frequent Contributor
timestamp: August 10, 2014, 06:12:43 pm
content: I tried something to that effect,where I scoped the DMX signal that was going INTO my uC from the Max485, and tried to see what the duration of the bit is (just to get an idea of how long it is), but it looks like about 35uS (Scope set on 10uS/div. I think it is supposed to be something like 4uS per bit, but the edges are not clear. It looks like overlapping from several bits being shown during at the same time (from say a couple of sweeps)I only have an analogue 20mhz scope, so I don't know how to get clear accurate reading.I Sent a char 'U' out on the Usart, but the bit time does look to be 4uS.I even took the ASM version directly from the Appnote, and made some changes to the config bits, as well as setting the registers to up the speed to the 8mhz of my Micro, and then adjusted the SPBRG from 15 down to 7 (some calculators say it must be 1),but that is also just hanging around the same point...And I thought this was going to be an easy one.Maybe there is something different about the 18f2420 micro that messes it up.

author: kolbep
author_rank: Frequent Contributor
timestamp: August 12, 2014, 08:27:58 pm
content: Having dug around a lot on the net, I see that lots of people discourage using frame error to detect the long break.So I am trying my own code, where a High to Low transition on RB2 triggers an interrupt.In the interrupt it resets timer1, and then sets a edge flag, it also changes the interrupt edge detection for the next part to trigger an interrupt on low to high.Then when the interrupt occurs, it reads off the timer1. If it is a low time, then ignore it because it is probably a bit. If it is longer than 128 Cycles in the timer, then it is most likely the 176ms break. In which case it sets a flag for the long break detection, and drops out of the ISR.My main loop then keeps on polling this flag. As soon as the flag goes high, it is supposed to start reading from the USART.I have a problem when, If I enable Timer1's T1_SOURCE_INT, it stops my program from ever going into the ISR (Even though I do not even have Interrupts enabled for Timer1)Any clues.....Thanks for all your helpCode:/** File: DMXRecv.c* Author: Peter** Created on 09 August 2014, 17:26*//** C O N F I G U R A T I O N B I T S ******************************/#pragma config OSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H#pragma config PWRT = OFF, BOREN = OFF //,BORV = 30 // CONFIG2L#pragma config WDT = OFF, WDTPS = 32768 // CONFIG2H#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTB // CONFIG3H#pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L#pragma config CP0 = OFF, CP1 = OFF //, CP2 = OFF, CP3 = OFF // CONFIG5L#pragma config CPB = OFF, CPD = OFF // CONFIG5H#pragma config WRT0 = OFF, WRT1 = OFF//, WRT2 = OFF, WRT3 = OFF // CONFIG6L#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H#pragma config EBTR0 = OFF, EBTR1 = OFF//, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L#pragma config EBTRB = OFF // CONFIG7H/** I N C L U D E S **************************************************/#include <timers.h>#include <string.h>#include <usart.h>#include <pwm.h>#include <stdio.h>#include <stdlib.h>#include <delays.h>#include "xlcd.h"#include <portb.h>/***//** PROTOTYPES *****************************************************/void setup_usart(void);// setup baud rate etc. of USARTvoid setup_pwm(void);// setup pwm etc/* declare statically allocated uinitialized variables *********/#pragma udatachar RXbuffer;char DataVal = 0;intslot = 0;int channel = 1;int brkfl;unsigned int t1val;char at1val;int lbflag; //THIS FLAG SAYS THERE IS A LONG BREAK, SO START USARTchar chanval;/* Declare executable instructions ****************************///#pragma code// Delays for XLCD.hvoid DelayFor18TCY( void ) { Delay1KTCYx(12); }void DelayPORXLCD( void ) { Delay10KTCYx(100); }void DelayXLCD( void ) { Delay1KTCYx(11); }void reset (void) { //This Routine will reset the uC_asm reset _endasm}void high_interrupt (void); /* prototype needed for 'goto' below */#pragma code HIGH_INTERRUPT_VECTOR = 0x8void high_ISR (void){_asmgoto high_interrupt_endasm}#pragma code /* allow the linker to locate the remaining code */#pragma interrupt high_interruptvoid high_interrupt (void) {putrsXLCD ("Abcd ");if (INTCON3bits.INT2IF==1) {putrsXLCD("B ");if (brkfl==0) { //THIS WAS A HIGH TO LOWWriteTimer1(0); //RESET THE TIMERputrsXLCD("C ");INTCON2bits.INTEDG2=1; //Change to rising edgePORTB=PORTB; //Clear Mismatchbrkfl=1; //Change the Flag so we know next step};if (brkfl==1) { //THIS WAS A LOW TO HIGHputrsXLCD("P ");t1val=ReadTimer1();INTCON2bits.INTEDG2=0; //Change to falling edge detectionPORTB=PORTB; //Clear Mismatchbrkfl=0;while(BusyXLCD()); //Wait for LCDitoa(t1val,at1val); // Convert to AsciiputsXLCD(at1val);putrsXLCD(" ");if (t1val>=128) {//THIS IS A LONG BREAK, SO WE CAN START THE USARTlbflag=1;//putsXLCD(at1val);putrsXLCD("D ");while(1);};};};INTCON3bits.INT2IF=0; //ByeByeFlagINTCON3bits.INT1IF =0; //Re-en``able all interrupts}void EnableHighInterrupts (void){RCONbits.IPEN = 1; /* enable interrupt priority levels */INTCONbits.GIEH = 1; /* enable all high priority interrupts */}#pragma interrupt low_interruptvoid low_interrupt (void) {WriteCmdXLCD ((0x80+0x42));putrsXLCD("HEY A LOW");// INTCON3bits.INT1IF =0; //Re-enable all interruptswhile(1);}void EnableLowInterrupts (void){RCONbits.IPEN = 1; /* enable interrupt priority levels */INTCONbits.GIEL = 1; /* enable all high priority interrupts */}void main(void) {// set internal oscillator to 16MHzOSCCON = 0x60;// IRCFx = 110 MAKES CLOCK 4MHZOSCTUNEbits.PLLEN = 1;// x4 PLL MAKES CLOCK 16MHZLATA=0x00;LATB=0x00;LATC=0x00;TRISA=0x00; // 0=OUT, 1=INTRISB=0x00;//&0x04; // O=OUT, 1=INTRISB=0xFF;TRISC=0xFF; // O=OUT, 1=IN//INITIALISE THE LCD// while( BusyXLCD() );OpenXLCD( FOUR_BIT & LINES_5X7);WriteCmdXLCD( BLINK_OFF & CURSOR_OFF);WriteCmdXLCD( SHIFT_DISP_LEFT );// while ( BusyXLCD());//BANNERputrsXLCD("DMX Buddy v1.1 ");OpenTimer1( TIMER_INT_OFF &T1_8BIT_RW &T1_SOURCE_INT &T1_PS_1_8 &T1_OSC1EN_OFF &T1_SYNC_EXT_OFF );PIE1bits.TMR1IE=0;IPR1bits.TMR1IP=0;// setup_usart();//SETUP PORT RB2 FOR HIGH TO LOW FOR BREAK DETECTION//CAUSES INTERRUPTbrkfl=0;OpenRB2INT( PORTB_CHANGE_INT_ON & FALLING_EDGE_INT & PORTB_PULLUPS_ON);// RCONbits.IPEN = 0; // priorityINTCONbits.GIE = 1; // enable interruptINTCONbits.RBIE = 1; // interrupt portB onEnableHighInterrupts;EnableLowInterrupts;while(1) { //MAIN LOOPif (lbflag==1) { //Long Break Detected. Start the USART Receinglbflag=0;putrsXLCD("pwpwpwpwpwpwpw");ReadUSART(); //Clear any errors/* Receive 512 bytes of data*/for (slot=0; slot<64; slot++){//if (RCSTAbits.FERR == 1) break;// check for framing errorwhile (!DataRdyUSART());// wait for data to be availableRXbuffer = ReadUSART();// read and copy data to RXbuffer}itoa((RXbuffer),chanval);putsXLCD(at1val);putrsXLCD("- -");};};}void setup_usart(void)// Set USART to transmit @ 250KB{OpenUSART( USART_TX_INT_OFF &// disable TX interruptUSART_RX_INT_OFF &// enable RX interruptUSART_ASYNCH_MODE &// set asynchronous modeUSART_NINE_BIT &// set 9-bit data modeUSART_CONT_RX &// set port continues RXUSART_BRGH_HIGH, 15);// uses high speed formula, 250KBdBAUDCONbits.BRG16 = 1;// set 16 bit async mode}

author: dannyf
author_rank: Super Contributor
timestamp: August 12, 2014, 08:43:25 pm
content: Code:while(BusyXLCD()); //Wait for LCDitoa(t1val,at1val); // Convert to Ascii1) try not loop around in an isr; you want it to be quick;2) Those xlcd routines are probably long. Also, you will need to make sure that they are not used outside of the isr as well;3) itoa() routines are often very long.So I am trying my own code, where a High to Low transition on RB2 triggers an interrupt.In the interrupt it resets timer1, and then sets a edge flag, it also changes the interrupt edge detection for the next part to trigger an interrupt on low to high.Then when the interrupt occurs, it reads off the timer1. If it is a low time, then ignore it because it is probably a bit. If it is longer than 128 Cycles in the timer, then it is most likely the 176ms break. In which case it sets a flag for the long break detection, and drops out of the ISR.That is fairly simple and can be done fairly easily. Two suggestions:1) Need to make sure that the timer can detect overflow.2) Use a constantly running timer;If you are running out of external interrupts, use pin-change interrupts here -> will make your coding simpler.Also, consider the use of capture.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 12, 2014, 10:28:46 pm
content: Quote from: kolbep on August 12, 2014, 08:27:58 pmThe only reason to not do that is if there are issues with a particular device - check the errataA break should generally show up as a zero byte as well as setting the FERR flag.So I am trying my own code, where a High to Low transition on RB2 triggers an interrupt.In the interrupt it resets timer1, and then sets a edge flag, it also changes the interrupt edge detection for the next part to trigger an interrupt on low to high.It's easier than that. Int on -ve edge sets a timer int. to fire in the normal stopbit position.The timer int samples the input and if low, you have a break.QuoteWhy would you do this in foreground? Much easier if all the DMX acquistion, including addressing, is done under interrupts, and just throws a flag to the foreground task when a frame is received.

author: kolbep
author_rank: Frequent Contributor
timestamp: August 13, 2014, 06:07:47 am
content: Quote from: mikeselectricstuff on August 12, 2014, 10:28:46 pmPickit2 is reporting my Silicon as rev 07. Here are all the errata for all the revisions, does anything stand out as being the cause of the Framing Error not being detected :Code:18. Module: EUSARTWhen performing back-to-back transmission in9-bit mode (TX9D bit in the TXSTA register isset), an ongoing transmissionís timing can becorrupted if the TX9D bit (for the nexttransmission) is not written immediately following the setting of TXIF. This is because anywrite to the TXSTA register results in a reset ofthe baud rate timer which will effect any ongoingtransmission.Work aroundLoad TX9D just after TXIF is set, either by pollingTXIF or by writing TX9D at the beginning of theInterrupt Service Routine, or only write to TX9Dwhen a transmission is not in progress(TRMT = 1).19. Module: EUSARTWhen performing back-to-back transmission in 9-bitmode (TX9D bit in the TXSTA register is set), thesecond byte may be corrupted if it is written intoTXREG immediately after the TMRT bit is set.Work aroundExecute a software delay, at least one-half thetransmissionís bit time, after TMRT is set and priorto writing subsequent bytes into TXREG.Date Codes that pertain to this issue:All engineering and production devices.6. Module: Enhanced UniversalSynchronous ReceiverTransmitter (EUSART)One bit has been added to the BAUDCON registerand one bit has been renamed. The added bit isRXDTP and is in the location, BAUDCON<5>. Therenamed bit is the TXCKP bit (BAUDCON<4>),which had been named SCKP.The TXCKP (BAUDCON<4>) and RXDTP(BAUDCON<5>) bits enable the Synchronousmode TX and RX signals to be inverted (polarityreversed). RXDTP has no effect on theSynchronous mode DT signal.Register 18-3, on page 204, will be changed asshown.Work aroundNone required.Date Codes that pertain to this issue:All engineering and production devices.5. Module: Enhanced UniversalSynchronous AsynchronousReceiver Transmitter (EUSART)In rare situations when interrupts are enabled,unexpected results may occur if:• The EUSART is disabled (the SPEN bit,RCSTA <7>, = 0)• The EUSART is re-enabled (RCSTA <7> = 1)• A two-cycle instruction is executedWork aroundAdd a 2-TCY delay after re-enabling the EUSART.1. Disable Receive Interrupts (RCIE bit,PIE1<5>, = 0).2. Disable the EUSART (RCSTA <7>, = 0).3. Re-enable the EUSART (RCSTA <7> = 1).4. Re-enable Receive Interrupts (PIE1<5> = 1).(This is the first TCY delay.)5. Execute an NOP instruction.(This is the second TCY delay.)QuoteBefore this project, the furtherest I managed to get with the PIC was flashing LEDS, A countdown timer, and Reading Voltages using the ADC. I would really appreciate if you could please show me a snippet of code that describes what you say above. I am having a bit of hassle comprehending it. Does it mean that I must set up the timer with a period corresponding to 4m/s, then when the pin goes -ve edge, reset the Timer and enable interupt. Then in that interrupt I must look if the pin is still low?I know the itoa and xlcd are processor hogs, I just wanted an easy way for me to read out timings, etc, while I am trying to debug. Once I am far enough along, I can remove them...Thanks for the help

author: dannyf
author_rank: Super Contributor
timestamp: August 13, 2014, 10:34:30 am
content: It is much better for you if you write the code - we can help you get there.The isr would basically look like this:Code://this is pcintif (sensor pin is high) { //the pin must have gone through a low->high transition -> rising edgereset timer;clear sTimer's value;} else { //the pin is low -> it must have gone through a high->low transistion -> falling edgesave timer's value to sTimer; //save timer's value into a shadow variableset a flag to indicate new data;}...in main...if (flag is set) { //new data has arrivedif (sTimer > TIMER_THRESHOLD) { //this is a long pulse//do something} else { //pulse is short//do something else}Hope it helps.

author: kolbep
author_rank: Frequent Contributor
timestamp: August 13, 2014, 05:11:17 pm
content: Ok, I am trying the basics now, just to understand the USART. Reading the usart and check for Framing errors.If I have the RC7 pin connected to the Max485, I expect it to display random values, and to indicate a framing error. But all I get printed on the XLCD is -4 and the bit indicating framing error never comes up...Here is my code:Code:/** File: DMXRecv.c* Author: Peter** Created on 09 August 2014, 17:26*//** C O N F I G U R A T I O N B I T S ******************************/#pragma config OSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H#pragma config PWRT = OFF, BOREN = OFF //,BORV = 30 // CONFIG2L#pragma config WDT = OFF, WDTPS = 32768 // CONFIG2H#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTB // CONFIG3H#pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L#pragma config CP0 = OFF, CP1 = OFF //, CP2 = OFF, CP3 = OFF // CONFIG5L#pragma config CPB = OFF, CPD = OFF // CONFIG5H#pragma config WRT0 = OFF, WRT1 = OFF//, WRT2 = OFF, WRT3 = OFF // CONFIG6L#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H#pragma config EBTR0 = OFF, EBTR1 = OFF//, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L#pragma config EBTRB = OFF // CONFIG7H/** I N C L U D E S **************************************************/#include <timers.h>#include <string.h>#include <usart.h>#include <pwm.h>#include <stdio.h>#include <stdlib.h>#include <delays.h>#include "xlcd.h"unsigned int usartval;unsigned char ausartval;//#include <porta>/***//** PROTOTYPES *****************************************************/void setup_usart(void);// setup baud rate etc. of USART/* Declare executable instructions ****************************/// Delays for XLCD.hvoid DelayFor18TCY( void ) { Delay1KTCYx(1); }void DelayPORXLCD( void ) { Delay1KTCYx(10); }void DelayXLCD( void ) { Delay1KTCYx(1); }void reset (void) { //This Routine will reset the uC_asm reset _endasm}void high_interrupt (void); /* prototype needed for 'goto' below */#pragma code HIGH_INTERRUPT_VECTOR = 0x8void high_ISR (void){_asmgoto high_interrupt_endasm}#pragma code /* allow the linker to locate the remaining code */#pragma interrupt high_interruptvoid high_interrupt (void) {}void EnableHighInterrupts (void){RCONbits.IPEN = 1; /* enable interrupt priority levels */INTCONbits.GIEH = 1; /* enable all high priority interrupts */}void main(void) {// set internal oscillator to 16MHzOSCCON = 0x60;// IRCFx = 110 MAKES CLOCK 4MHZOSCTUNEbits.PLLEN = 1;// x4 PLL MAKES CLOCK 16MHZLATA=0x00;LATB=0x00;LATC=0x00;TRISA=0x00; // 0=OUT, 1=INTRISB=0x00; // O=OUT, 1=INTRISC=0xff; // O=OUT, 1=IN//INITIALISE THE LCD//while( BusyXLCD() );OpenXLCD( FOUR_BIT & LINES_5X7);WriteCmdXLCD( BLINK_OFF & CURSOR_OFF);WriteCmdXLCD( SHIFT_DISP_LEFT );putrsXLCD("DMX Buddy v2.1 ");///////////////////////////////////////////////////////////////////////////////// LETS TEST THE USART FOR FRAMING ERRORSsetup_usart();PORTAbits.RA7=0; //CLEAR THE LEDwhile(1){int usartval=ReadUSART();itoa (usartval,ausartval);putsXLCD(ausartval);putrsXLCD(" ");Delay10KTCYx(500);if (RCSTAbits.FERR){PORTAbits.RA7=1;}};EnableHighInterrupts;while(1) { //MAIN LOOP};}void setup_usart(void)// Set USART to transmit @ 250KB{OpenUSART( USART_TX_INT_OFF &// disable TX interruptUSART_RX_INT_OFF &// enable RX interruptUSART_ASYNCH_MODE &// set asynchronous modeUSART_NINE_BIT &// set 9-bit data modeUSART_CONT_RX &// set port continues RXUSART_BRGH_HIGH, 15);// uses high speed formula, 250KBdBAUDCONbits.BRG16 = 1;// set 16 bit async mode}Where can I start looking for this (my) bug???

author: kolbep
author_rank: Frequent Contributor
timestamp: August 13, 2014, 08:38:16 pm
content: Looks like I am getting Frame Errors, after setting every bit manunally, and not using the OpenUSART routine (At least my Test Light on RA7 is coming on):Now to figure out why it is still showing 0 on the LCD, instead of another random value.....Code:///////////////////////////////////////////////////////////////////////////////// LETS TEST THE USART FOR FRAMING ERRORS// setup_usart();// Delay10KTCYx(100);// putrsXLCD("DMX Buddy v2.3 ");while(1) {PORTAbits.RA7=0;SPBRGH=.15;TRISCbits.TRISC7=1;TRISCbits.TRISC6=1;TXSTAbits.TXEN=0; //DISABLE TXTXSTAbits.BRGH=1;BAUDCONbits.BRG16=1;TXSTAbits.SYNC=0;RCSTAbits.SPEN=1; //ENABLE SerialPRCSTAbits.RX9=1;RCSTAbits.ADDEN=0; //??????RCSTAbits.CREN=1; //ENABLE RX// while(!(PIR1bits.RCIF)); //WAIT FOR RECEPTION COMPLETE// if(RCSTAbits.FERR){// PORTAbits.RA7=1;// recvreg=RCREG; //CLEAR THE ERROR// };while(RCSTAbits.FERR) {recvreg=RCREG;PORTAbits.RA7=1;};//while(!(PIR1bits.RCIF)); //WAIT FOR ANOTHER BYTE//PIR1bits.RCIF=0;//while(!(RCSTAbits.FERR)) {PORTAbits.RA7=0;recvreg=RCREG;itoa(recvreg,arecvreg);//Delay10KTCYx(1);//putsXLCD(arecvreg);Delay10KTCYx(1);putsXLCD(arecvreg);putrsXLCD(". ");}

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 13, 2014, 10:18:59 pm
content: Beware peripheral libraries - they may be hiding stuff from you. Best to bash the hardware direct if doing something vaguely nonstandard

author: matkar
author_rank: Regular Contributor
timestamp: August 14, 2014, 09:12:11 pm
content: Quote from: kolbep on August 09, 2014, 09:24:22 pmSPBRG values of less than 10 can lead to inaccurate bitrate settings. Here below is a macro that calculates adequate baudrate according to your clock. It's written in assembler, but you'll get the idea.Code:SERIAL_1_INIT_PORT#define BRGH_HIGH ;Select for BRGH=1SPBRG_V1 = CLOCK_FREQ/UARTINT_BAUDRATE;SPBRG_V2 = SPBRG_V1 /.16 ;SPBRG_V22 = (SPBRG_V1 * .10) /.16 ;if ( ((SPBRG_V2*.10) - SPBRG_V22) >= .5)SPBRG_V2 ++;endifif (SPBRG_V2 > 0xff)SPBRG_V3 = SPBRG_V2SPBRG_V2 = SPBRG_V3 / .4SPBRG_V22 = (SPBRG_V3 * .10) /.4 ;if ( ((SPBRG_V2*.10) - SPBRG_V22) >= .5)SPBRG_V2 ++;endif#undefine BRGH_HIGH ;BRGH = 0endifbsf TXSTA,BRGH ;Enable BRGHSPBRG_VAL=SPBRG_V2 - D'1' ;Calculated SPBRG register valueif SPBRG_VAL > .255error "Calculated SPBRG register value is out of range"endifif SPBRG_VAL <= .10error "Calculated SPBRG register value is too low"endif#ifndef SPBRG_VALerror"SPBRG reload value not def."#endifmovlwSPBRG_VALmovwf SPBRGbcfTXSTA,SYNC ; AsyncbsfRCSTA,SPEN ; serial 1 enablebcfTXSTA,TX9 ; Tx 8-bitbsfTXSTA,TXEN ; Tx enabledbcfRCSTA,RX9 ; Rx 8-bitbsfRCSTA,CREN ; Rx enabled;bcfIPR1,RCIP; set serial 1 Rx interrupt as low prioritybsfPIE1,RCIE ; enable Rx interruptbcfRCON,IPEN ; single interrupt priority mode selectionbsfINTCON,GIE; enable global priority interruptbsfINTCON,PEIE ; enable peripheral interruptreturn

author: kolbep
author_rank: Frequent Contributor
timestamp: August 22, 2014, 05:05:16 pm
content: Now that there is a time crunch, and the fact that I can only borrow a USB Dmx dongle for a few days at a time every couple of weeks,I have decided to go with a tried and tested method.http://dbprototyping.com/dmxTXRX.htmhas taken the Microchip Appnote, and converted it to work with C18 and the PIC18F4xK20 series.I have ordered myself the same chip that they use, then I will modify their code to my own needs (They just have PWM dimming, but I want to make it modular so that I can have Relay Output, Phase Controlled Triac, and PWM'd transistor outputs (or a combination).I know it is a bit of a cheat, and I am upset that I have to resort to this. It would be more satisfying to have figured out why it does not work with the PIC18F2420 series, but time is against me....