USART doesn't work on pic16f1788  - Page 1
Forum section: electronics / general

author: karguet
author_rank: Newbie
timestamp: April 05, 2022, 11:47:17 am
content: Hi,I'm testing an usart communication on pic16f1788, at the same time I'm using an arduino board (serial monitor), to check that the commication correct. But I'm not recieving any thing on arduino (using the serial monitor).Could any one tell me what is the problem please ?I put the code of both (Mplab & Arduino) below.Is there any thing similar to serial monitor of the arduino on Mplab ?ThanksCode:// ----------------Mplab Code ------------------------#include <xc.h>#include <stdio.h>#include <stdlib.h>#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)// CONFIG2#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)#pragma config VCAPEN = OFF // Voltage Regulator Capacitor Enable bit (Vcap functionality is disabled on RA6.)#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)#pragma config LPBOR = OFF // Low Power Brown-Out Reset Enable Bit (Low power brown-out is disabled)#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)#define _XTAL_FREQ 16000000void init_UART(){TXSTA = 0x24;RCSTA = 0x90;SPBRG = 407; // Baud = 9600 Fosc = 16 MHzBAUDCON = 0x08; // 16-bit Baud Rate Generator is usedAPFCON1bits.TXSEL = 0;}void UART_Tx (char data){while (TXIF == 0){}TXREG = data;}char UART_Rx(){while (RCIF ==1){}return RCREG;}void main(void){TRISCbits.TRISC6 = 0; // TxTRISCbits.TRISC7 = 1; // Rxint i=0;char data = 'U'; // U - 0b01010101 just for testingOSCCON = 0x7A; // 16 MHz//OSCCON = 0x72; // 8 MHzinit_UART();UART_Tx(data);UART_Tx(data);UART_Tx(data);}// ---------------- Arduino Code ------------------------void setup(){Serial.begin(9600);}void loop(){char data;while (Serial.available()){data = Serial.read();Serial.println(data);}}

author: DavidAlfa
author_rank: Super Contributor
timestamp: April 05, 2022, 02:10:19 pm
content: You have BRGH and BRG16 bits enabled, so the Baudrate formula is: FOSC/[4 (n+1)]Your calculated the value for 16MHz (Wrong, you're running at 32MHz because PLLEN is set), but value is wrong even for 16MHz:Code:16.000.000/[4 (407+1)] = ~9804 baud, should have been 416 (9592 baud)For 9600 at 32MHz, BRG value is 832 (0x340):Code:32.000.000/[4 (832+1)] = ~9604 baudBut your real problem is there:Code:SPBRG = 407; // Baud = 9600 Fosc = 16 MHzBRG is divided in two 8-bit registers: SPBRGH (MSB) and SPBRGL (LSB)"SPBRG" name refers to SPBRGL for legacy purposes, it's not the 16-bit register.So 407(0x197) is higher than what 8-bit can hold (0xFF, 255), you're really writing 0x97 to it.You should have seen a BIG compiler warning... Ignoring them is a very bad idea!Code:warning: implicit conversion from 'int' to 'unsigned char' changes value from 407 to 151 [-Wconstant-conversion]SPBRG = 407; // Baud = 9600 Fosc = 16 MHz~ ^~~_XTAL_FREQ should reflect the real frequency. With PLL enabled, you're running at 32MHz, not 16MHz!FYI, TX TRIS setting doesn't matter when UART is enabled, only Rx pin must be set as input:Code:Setting the SPEN bit of the RCSTA register enables the EUSART and automatically configures the TX/CK I/O pin as an output.The programmer must set the corresponding TRIS bit to configure the RX/DT I/O pin as an input.Also, it's a nice idea to check if the pic is working at all by toggling a led every 1sec, ensuring the output timing is correct.(You will quickly detect if your oscillator frequency or XTAL_FREQ are wrong)Finally, unless required to do so, it's usually safer to turn off the peripheral before configuring it.Fix:Code:#include <xc.h>#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)// CONFIG2#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)#pragma config VCAPEN = OFF // Voltage Regulator Capacitor Enable bit (Vcap functionality is disabled on RA6.)#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)#pragma config LPBOR = OFF // Low Power Brown-Out Reset Enable Bit (Low power brown-out is disabled)#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)#define _XTAL_FREQ 32000000 // Should be correct for correct delay!void init_UART(){RCSTA = 0x0; // Clear and turn off the USARTTRISC7 = 1; // RC7 as inputAPFCON1bits.TXSEL = 0; // TX is on pin RC6APFCON1bits.RXSEL = 0; // RX is on pin RC7TXSTA = 0x24; // Enable TX and BRGHBAUDCON = 0x08; // Enable BRG16SPBRGH = 0x03; // Baud = 9600 Fosc = 32 MHzSPBRGL = 0x40; // Baud = 9600 Fosc = 32 MHzRCSTA = 0x0; // Enable USART and Continuous Receive mode}void UART_Tx (char data){while(!TXIF);TXREG = data;}char UART_Rx(){while (RCIF);return RCREG;}void sendStr(char *str){while(*str)UART_Tx(*str++);}void main(void){TRISC6=0; // LED outputOSCCON = 0x7A; // 16 MHz with PLL off, 32MHz with PLL oninit_UART(); // Init UARTwhile(1){ // Keep sending "Hello" and toggling the led every secondsendStr("Hello");LATC6 = !LATC6;__delay_ms(1000);}}

author: tepalia02
author_rank: Regular Contributor
timestamp: May 07, 2022, 03:05:06 pm
content: I think it will be easier if you test with miKro C's in-built USART library.