dsPIC30F4013 UART issue
Hi guys, I'm hoping you can help me solve a strange issue I'm facing with the UART module when trying to communicate a laptop with a dsPIC30F4013 through a serial-USB converter. I'm currently using a simple Python (TKInter) GUI to control very basic Led behavior (On/Off/Blink) just to figure out the intricacies, though this will later be used to communicate 2 MCUs through a MAX232, but I'm getting ahead of myself...
Expected behavior: The GUI has 3 buttons, ON button sends a '1', OFF button sends a '2' and Blinking mode sends a '3'. When button is pressed, dsPIC should control, accordingly, a Led connected to RF4.
Current behavior: The pulse is sent, but the dsPIC doesn't respond to '1' (ON) or '3' (Blink) commands, it only responds to '2' (OFF), but it doesn't even behave as expected: it turns the Led on for about 300-400 ms and then turns it back off, once per button press, no blink. This behavior is always the same, regardless of which button I press first, or how many times I press any button (which I think indicates that there are no "buffer delays", so to speak).
The GUI uses UTF-8 encoding and I have corroborated (oscilloscope) that the data arriving at the dsPIC's U1RX pin corresponds to the expected UTF-8 code (1 = 0b00110001, 2 = 0b00110010, 3 = 0b00110011).
I found a similar issue here (/forums/m827522.aspx, please add microchip.com before the extension, due to forum issues with links, etc.) however, the solution that helped OP doesn't work for me. I have used RAM, volatile variables as suggested by users "ric" and "balmerjd" to ensure I'm checking every sent value against my designated conditions and not losing the data at U1RXREG after every read, which follows FIFO logic. I have configured all related registers (U1MODE, U1STA, U1RXREG, etc.) with help of the dsPIC30F FRM and the specific 4013 datasheet and, as far as I can tell, the settings are correct (for 8-bit, no parity bits, one stop bit).
You'll find my code attached below, with the MCU's code at the top, followed by the Python TKinter code (where I doubt there'll be any issues, since it's fairly simple and, as I've stated, I've made sure that the data sent to MCU's pin matches the number).
You'll notice that, in my code, I left out the following section from balmerjd's code:
while (1)
{
if (uart_received)
{
while(U1STAbits.UTXBF == 1);
U1TXREG = dataIn;
uart_received=0;
}
}
Reason being, I don't really understand why he's checking bit UTXBF and writing to U1TXREG, since, as far as I understood OP's question, they're not trying to transmit anything (nor am I), but run a function in main() depending on what's received at U1RXREG. In case you're wondering if this is why the code isn't working for me, its inclusion in my project doesn't help either.
As always, any hints are really appreciated.
Thanks in advance,
Rob
Software/Hardware used:
MPLAB X IDE v5.40
XC16 Compiler
PICkit 3
USB to Serial DB9 (male) RS232 cable
#define FCY 5000000UL
#include <p30F4013.h>
#include <libpic30.h>
#include "config.h"
volatile unsigned char dataIn = 0;
volatile int uart_received = 0;
void config_uart(void);
int main(void) {
TRISFbits.TRISF2=1; //RF2/U1RXpin [25] as input
TRISFbits.TRISF4=0; //Output LED
config_uart();
while(1){
if(uart_received){
switch(dataIn){
case '1':
LATFbits.LATF4 = 1; //Turn LED ON
uart_received=0;
break;
case '2':
LATFbits.LATF4 = 0; //Turn LED OFF
uart_received=0;
break;
case '3': //Blink LED
LATFbits.LATF4 = 1;
__delay_ms(400);
LATFbits.LATF4 = 0;
__delay_ms(400);
uart_received=0;
break;
}
}
}
return 0;
}
void config_uart(void){
U1MODEbits.UARTEN = 0; //Disable UART1 prior to config.
U1MODEbits.STSEL = 0; //1 Stop bit
U1MODEbits.PDSEL = 0b00; //8-bit data, no parity bit
U1STAbits.URXISEL = 0b00; //Interrupt flag set when a character is received
U1BRG = 32; //Desired Baud Rate: 9600, with 20MHz Xtal; [ Fcy/(16*BR) - 1] = [5,000 MHz/153,600 -1] = 31.5 )
IPC2bits.U1RXIP = 5; //Set Receive Interrupt Priority
IEC0bits.U1RXIE = 1; //Enable Receive Interrupt
IFS0bits. U1RXIF = 0; //Lower Receive Interrupt Flag
U1MODEbits.UARTEN = 1; //Enable UART1
}
void __attribute__ ((__interrupt__,no_auto_psv)) _U1RXInterrupt(void){
unsigned char byteIn=0x00;
byteIn=U1RXREG;
if(byteIn == '1' || byteIn == '2' || byteIn == '3'){ //ON, OFF & Blinking commands, respectively
dataIn = byteIn; //If byteIn corresponds to a command, store...
}
else{ //...Otherwise ignore
dataIn = '-';
}
if(byteIn!=0x00){ //To avoid cycling in interrupt, raise global flag polled in main()
uart_received=1;
}
IFS0bits.U1RXIF = 0; //Clear Reception Interrupt flag
}
Python GUI code
from tkinter import *
from tkinter.font import Font
from time import sleep
import serial
from serial import Serial
import time
import sys
port = serial.Serial()
port.baudrate=9600
port.timeout=3
port.port='COM4'
port.open()
print('Serial Port ready')
window = Tk()
window.title("Python - dsPIC30F4013")
window.geometry('320x300')
def button1():
global vent
mystring = str(1)
b = mystring.encode('UTF-8')
print("Button 1 has been pressed")
port.write(b)
tex.delete(1.0,END)
tex.insert(1.0, "Led On")
def button2():
global vent
mystring = str(2)
b = mystring.encode('UTF-8')
print("Button 2 has been pressed")
port.write(b)
tex.delete(1.0,END)
from tkinter import *
from tkinter.font import Font
from time import sleep
import serial
from serial import Serial
import time
import sys
port = serial.Serial()
port.baudrate=9600
port.timeout=3
port.port='COM4'
port.open()
print('Serial Port ready')
window = Tk()
window.title("Python - dsPIC30F4013")
window.geometry('320x300')
def button1():
global vent
mystring = str(1)
b = mystring.encode('UTF-8')
print("Button 1 has been pressed")
port.write(b)
tex.delete(1.0,END)
tex.insert(1.0, "Led On")
def button2():
global vent
mystring = str(2)
b = mystring.encode('UTF-8')
print("Button 2 has been pressed")
port.write(b)
tex.delete(1.0,END)
tex.insert(1.0, "Led Off")
def button3():
global vent
mystring = str(3)
b = mystring.encode('UTF-8')
print("Button 3 has been pressed")
port.write(b)
tex.delete(1.0,END)
tex.insert(1.0, "Led Blinking")
l1=Button(window,text='LED On',command=button1, cursor='circle')
l2=Button(window,text='LED Off',command=button2, cursor='circle')
l3=Button(window,text='LED Blink',command=button3, cursor='circle')
lab1=Label(window, text='Led state', width=15, height=3)
lab2=Label(window, text='Python serial w/PIC', width=38, height=4)
tex=Text(window,width=20,height=2)
l1.place(x=130,y=200)
l2.place(x=220,y=200)
l3.place(x=160,y=250)
lab1.place(x=150,y=100)
lab2.place(x=50,y=40)
tex.place(x=125,y=140)
window.mainloop()
port.close()
print('Port closed')
sys.exit(0)