View previous topic :: View next topic |
Author |
Message |
Joseph T.
Joined: 25 Feb 2019 Posts: 2
|
int_tbe on dsPIC33FJ issue |
Posted: Thu Feb 28, 2019 10:37 am |
|
|
Hi everyone,
I'm a new user of the forum and recently I started using CCS.
I ask for your help because I need to configure the UART1 based on interrupt of a dsPIC33FJ32MC302.
The interrupt in rx works fine but I could not get #int_tbe to work. I followed what suggested in the EX_STISR.c example but the interrupt does not fire ...
Could someone help me solve this problem?
Below is the minimum code I am trying to transmit on the serial using int_tbe.
MCU: dsPIC33FJ32MC302
Compiler: PCD v5.017
Code: | #include <33FJ32MC302.h>
#FUSES WPRES32 //Watch Dog Timer PreScalar 1:32
#FUSES WPOSTS1 //Watch Dog Timer PostScalar 1:1
//#FUSES PROTECT_HIGH //General Segment Code Protect High Security
//#FUSES PROTECT
#FUSES FRC_DIV_BY_16 //Internal FAST RC oscillator with 16x PLL
#FUSES OSCIO //OSC2 is general purpose output
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOPWMPIN //PWM outputs drive active state upon Reset
#FUSES NOJTAG //JTAG disabled
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#use delay(clock=40000000)
#pin_select U1TX = PIN_B12
#pin_select U1RX = PIN_B15
#use rs232(UART1, baud = 115200, PARITY = N, BITS = 8, ERRORS)
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#word AD1PCFGL = 0x032C
#word TRISA = 0x02C0
#word PORTA = 0x02C2
#word LATA = 0x02C4
#word TRISB = 0x02C8
#word PORTB = 0x02CA
#word LATB = 0x02CC
#bit TX1_En = LATB.5
#bit yLED = LATB.13
#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
#int_tbe
void serial_isr() {
if(t_next_in!=t_next_out)
{
putc(t_buffer[t_next_out]);
t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
}
else
disable_interrupts(int_tbe);
TX1_En = 0;
yLED = 0;
}
void bputc(char c) {
short restart;
int ni;
restart=t_next_in==t_next_out;
t_buffer[t_next_in]=c;
ni=(t_next_in+1) % T_BUFFER_SIZE;
while(ni==t_next_out);
t_next_in=ni;
if(restart) {
TX1_En = 1;
yLED = 1;
enable_interrupts(int_tbe);
}
}
void main() {
setup_oscillator(OSC_INTERNAL, 40000000);
AD1PCFGL = 0x001F; // Set RA0...RA4 as digital I/O
TRISA = 0b0000000000000011;
LATA = 0b0000000000001000;
TRISB = 0b1000110100010011;
LATB = 0b0001001011001100;
TX1_En = 0;
yLED = 0;
enable_interrupts(INTR_GLOBAL);
printf(bputc,"\r\n\Running...\r\n");
while (TRUE) {
delay_ms(1000);
printf(bputc,"This is buffered data\r\n");
}
} |
Thanks in advance if you want to give me a hand!
Best Regards. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Feb 28, 2019 12:50 pm |
|
|
First thing is there is a separate st_isr example for PCD.
This is what you should start with. However it does have issues:
Use this instead:
Code: |
#include <33FJ32MC302.h>
#FUSES WPRES32 //Watch Dog Timer PreScalar 1:32
#FUSES WPOSTS1 //Watch Dog Timer PostScalar 1:1
#FUSES FRC_DIV_BY_16 //Internal FAST RC oscillator with 16x PLL
#FUSES OSCIO //OSC2 is general purpose output
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOPWMPIN //PWM outputs drive active state upon Reset
#FUSES NOJTAG //JTAG disabled
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#use delay(INTERNAL=39920834) //closest that internal can do. 1Hz under this.
#pin_select U1TX = PIN_B12
#pin_select U1RX = PIN_B15
#use rs232(UART1, baud = 115200, PARITY = N, BITS = 8, ERRORS)
#define TX1_En PIN_B5
#define yLED PIN_B13
#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
#int_tbe
void serial_isr() {
if(t_next_in!=t_next_out)
{
putc(t_buffer[t_next_out]);
t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
}
else
{
output_low(TX1_En);
output_low(yLED);
}
}
void bputc(char c) {
#bit U1TXIF = getenv("BIT:U1TXIF")
short restart;
int ni;
restart=(t_next_in==t_next_out);
t_buffer[t_next_in]=c;
ni=(t_next_in+1) % T_BUFFER_SIZE;
while(ni==t_next_out);
t_next_in=ni;
if(restart)
{
output_high(TX1_En);
output_high(yLED);
U1TXIF=TRUE;
}
}
void main() {
setup_adc(NO_ANALOGS);
enable_interrupts(INTR_GLOBAL);
enable_interrupts(INT_TBE);
printf(bputc,"\r\n\Running...\r\n");
while (TRUE) {
delay_ms(1000);
printf(bputc,"This is buffered data\r\n");
}
}
|
The big difference is that on the DsPIC's, you can leave the TX interrupt
and it won't keep re-triggering. However when you need to 'restart' what
has to happen is the interrupt flag is instead set.
A couple of comments:
The internal clock can't actually generate 40MHz. You get more accurate
timings if you set the requested frequency to one that can be generated.
You actually have to choose 1Hz above it, to get a timing selected, and
give the best timings. If you select 'INTERNAL' as I do here it does all
the setup for you. |
|
|
Joseph T.
Joined: 25 Feb 2019 Posts: 2
|
|
Posted: Fri Mar 01, 2019 9:43 am |
|
|
Thanks Ttelmah for the valuable advice! I have compiled your code and now I have a transmission. I could not find the example you were talking about in CCS files ... it will be that I have a slightly dated version.
In any case, thanks again for your time and for the help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Mar 01, 2019 11:20 am |
|
|
Ahh. The magic 'slightly too old' syndrome...
Yes it took CCS a while to update the examples to give a PCD one.
Annoyingly though it has an issue so doesn't quite work right.
Glad my 'fixed' one worked for you. |
|
|
|