Electronics > Microcontrollers

XC8 Soft UART on PIC16F819-Help please

(1/4) > >>

djsb:
Here is the main.c file of my software serial project


--- Code: ---/*
 * File: Main.c
 * Author: David J S Briscoe
 * PIC: 16F819 with INTERNAL RC OSC @ 8MHz, 5v
 * Program: 03_RS232
 * Compiler: XC8 (v2.40, MPLABX X v6.00)
 * Program Version: 1.0
 *               
 * Program Description: This Program Allows PIC16F819 to write to/from RS232.
 * .
 *
 * Hardware Description:
 *
 * Notes:
 *
 * 
 *                       
 * Created May 30th 2023, 11:32 AM
 * Last Updated:31st May 2023
 */

/*******************************************************************************
 Change History:
 Revision                  Description
 31st May 2023             Added calls to SUART_Init()routine and SUART_Write_Text("Hello") to main().
 1st to 2nd June 2023     
 
*******************************************************************************/
/*******************************************************************************
 TO DO:
 Task                      Details
 Check header file/s       Make sure calls in main() are same as in sw_uart.h and sw_uart.c.
       
 
*******************************************************************************/



/*******************************************************************************
 *Includes and defines
 ******************************************************************************/
#include "16F819_Internal.h" // Include header which sets  config fuses and oscillator frequency (set @ 8MHz) if using a XTAL.
#include "sw_uart.h"
#include <string.h>



/*******************************************************************************
 * Function: void initMain()
 *
 * Returns: Nothing
 *
 * Description: Contains initializations for main
 *
 * Usage: initMain()
 ******************************************************************************/

void initMain()
{
   
    OSCCONbits.IRCF = 0b0111; //Set the Clock to 8MHz when using internal oscillator.
                              /*
                              111 = 8 MHz (8 MHz source drives clock directly)
                              110 = 4 MHz
                              101 = 2 MHz
                              100 = 1 MHz
                              011 = 500 kHz
                              010 = 250 kHz
                              001 = 125 kHz
                              000 = 31.25 kHz (INTRC source drives clock directly)
                              Page 38 of the PIC16F819 data sheet.
                              */
    ADCON1bits.PCFG = 0b0110; //See page 82 of data sheet..
    ///////////////////////
     // Setup SW UART
     //////////////////////
   
    PORTA = 0x00;              //Clear Port A.
    PORTB = 0x00;              //Clear Port B.
   
   
}

/*******************************************************************************
 * Function: Main
 *
 * Returns: Nothing
 *
 * Description: Program entry point
 ******************************************************************************/

int main(void)
{
char letter;   
int n,i,j;
initMain();

// Initialize SW UART
SUART_Init();
__delay_ms(1000);
// Do forever.
while(1)
     {
    for ( n = 65; n < 91; n++)
        {
        letter = n;
        __delay_ms(1000);
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
        __delay_ms(1000);
        }
     }
    for ( i = 97; i < 123; i++)
        {
        letter = i;
        __delay_ms(1000);
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
        __delay_ms(1000);
        }
    for ( j = 48; j < 58; j++)
        {
        letter = n;
        __delay_ms(1000);
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
        __delay_ms(1000);
        }

}


--- End code ---

Here is the sw_uart.c code


--- Code: ---/*
 * File: sw_uart.c
 * Author: Armstrong Subero modified by David Briscoe
 * PIC: 16F819 w/Int OSC @ 8MHz, 5v
 * Program: Library file for Software UART
 * Compiler: XC8 (v1.41, MPLAX X v3.55)
 * Program Version: 1.0
 *
 * Program Description: This Library allows you to use a software UART with
 *                      the PIC microcontroller
 *                     
 * Created on June 1st, 2023
 */

#include "sw_uart.h"


/*******************************************************************************
 * Function: SUART_Init(void)
 *
 * Returns: Nothing
 *
 * Description: Initializes UART pins
 *
 ******************************************************************************/

void SUART_Init(void)
{
 UART_TX = 1; // TX pin is high in idle state
 
 UART_RX_DIR = 1; // Input
 UART_TX_DIR = 0; // Output
}


/*******************************************************************************
 * Function: unsigned char SUART_Receive(void)
 *
 * Returns: Nothing
 *
 * Description: recieves via soft UART
 *
 ******************************************************************************/

unsigned char SUART_Receive(void)
{
 // Initial at 0
 unsigned char DataValue = 0;

 //wait for start bit
 while(UART_RX==1);

 __delay_us(OneBitDelay);
 __delay_us(OneBitDelay/2); // Take sample value in the mid of bit duration

 for ( unsigned char i = 0; i < DataBitCount; i++ )
 {
  if ( UART_RX == 1 ) //if received bit is high
  {
   DataValue += (1<<i);
  }

  __delay_us(OneBitDelay);
 }

 // Check for stop bit
 if ( UART_RX == 1 ) //Stop bit should be high
 {
  __delay_us(OneBitDelay/2);
  return DataValue;
 }
 else //some error occurred !
 {
  __delay_us(OneBitDelay/2);
  return 0x000;
 }
}


/*******************************************************************************
 * Function: void SUART_Transmit(const char DataValue)
 *
 * Returns: Nothing
 *
 * Description: transmits via soft UART
 *
 ******************************************************************************/

void SUART_Transmit(const char DataValue)
{
 /* Basic Logic
   
    TX pin is usually high. A high to low bit is the starting bit and
    a low to high bit is the ending bit. No parity bit. No flow control.
    BitCount is the number of bits to transmit. Data is transmitted LSB first.

 */

 // Send Start Bit
 UART_TX = 0;
 __delay_us(OneBitDelay);

 for ( unsigned char i = 0; i < DataBitCount; i++ )
 {
  //Set Data pin according to the DataValue
  if(((DataValue>>i)&0x1) == 0x1 ) //if Bit is high
  {
   UART_TX = 1;
  }
  else //if Bit is low
  {
   UART_TX = 0;
  }

     __delay_us(OneBitDelay);
 }

 //Send Stop Bit
 UART_TX = 1;
 __delay_us(OneBitDelay);
}

/*******************************************************************************
 * Function: void SUART_Write_Text(char *text)
 *
 * Returns: Nothing
 *
 * Description: writes text via soft UART
 *
 ******************************************************************************/

void SUART_Write_Text(char *text)
{
  int i;
 
  for(i=0;text[i]!='\0';i++)
      SUART_Transmit(text[i]);
}


/*******************************************************************************
 * Function: void SUART_Read_Text(char *Output, unsigned int length)
 *
 * Returns: Nothing
 *
 * Description: reads text via soft UART
 *
 ******************************************************************************/

void SUART_Read_Text(char *Output, unsigned int length)
{
int i;
for(int i=0;i<length;i++)
Output[i] = SUART_Receive();
}


/*******************************************************************************
 * Function: void SUART_Write_Char(char a)
 *
 * Returns: Nothing
 *
 * Description: writes a character to SOFT UART
 *
 ******************************************************************************/

void SUART_Write_Char(char a)
{
    SUART_Transmit(a - 128);
}

--- End code ---

Here is the sw_uart.h header file


--- Code: ---/*
 * File: sw_uart.h
 * Author: Armstrong Subero modified by David Briscoe
 * PIC: 16F819 w/X OSC @ 8MHz, 5v
 * Program: Header file to setup PIC16F819 software UART
 * Compiler: XC8 (v1.41, MPLAX X v3.55)
 * Program Version 1.0
 *           
 * Program Description: This program header allows PIC to use a software UART
 *
 * Created on April 15th, 2017, 12:57 PM
 * Modified 1st June 2023.
 */


#include "16F819_Internal.h"

// bits per second
#define Baudrate 9600

// delay for UART
#define OneBitDelay (1000000/Baudrate)

// no parity no flow control
#define DataBitCount 8

// SW UART RX
#define UART_RX PORTBbits.RB4 //Wherever the compiler sees SW1_PORTB4 it substitutes PORTBbits.RB4
// SW UART TX
#define UART_TX PORTBbits.RB2 //Wherever the compiler sees LED_PORTB2 it substitutes PORTBbits.RB2



// RX pin direction register
#define UART_RX_DIR TRISBbits.TRISB4   //Ensure RB4 is an input pin (RX). Make same pins as in course material.

// TX pin direction register
#define UART_TX_DIR TRISBbits.TRISB2   //Ensure RB2 is an output pin (TX).

//Function Declarations
void SUART_Init(void);
unsigned char SUART_Receive(void);
void SUART_Transmit(const char);
void SUART_Write_Text(char *text);
void SUART_Write_Char(char a);
void SUART_Read_Text(char *Output, unsigned int length);


--- End code ---

And here is the 16F819_Internal.h file.

--- Code: ---/*
 * File: 16F819_Internal.h
 * Author: David J S Briscoe
 * PIC: 16F819 with INTERNAL OSC @ 8MHz, 5v
 * Program: Header file to setup PIC16F819
 * Compiler: XC8 (v2.40, MPLAX X v6.00)
 * Program Version 1.0
 *               
 *                *Changed comments and layout
 *                 
 * Program Description: This program header will allows setup of configuration
 *                      bits and provides routines for setting up internal
 *                      oscillator and includes all devices and MCU modules
 *
 * Created on February 24th, 2023
 ******************************************************************************/

/*******************************************************************************
 *Includes and defines
 ******************************************************************************/
// PIC16F819 Configuration Bit Settings
/*
Fuses: NOWDT,WDT,PUT,NOPUT,LP,XT,HS,EC_IO,INTRC_IO,INTRC,RC_IO,RC
//////// Fuses: NOMCLR,MCLR,NOBROWNOUT,BROWNOUT,NOLVP,LVP,CPD,NOCPD,WRT_600
//////// Fuses: WRT_400,WRT_200,NOWRT,DEBUG,NODEBUG,CCPB3,CCPB2,PROTECT
//////// Fuses: NOPROTECT
*/

// PIC16F819 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

//XC8 Standard Include
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

//Other Includes
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <math.h>


//For delay routines WHEN USING A CRYSTAL OSCILLATOR ONLY
#define _XTAL_FREQ 8000000

//MCU Modules Includes


--- End code ---

When I compile this using MPLABX and XC8 I get a few warnings but no errors. However all I get from PUTTY is garbage. I can also see the bursts of data on the R&S RTO1024 scope at work. I'm still learning how to use the scope and I havent figured out how to freeze and zoom into the waveform of the serial data and measure the timing yet. I have attached a zip file of the project below. Can anyone see any obvious mistakes (apart from in the comments which need review and updating in parts) or any ways to get the code working? How can I use a hardware timer in this code to make the timing more accurate? Thanks.


PS Ive been asked to use a 16F819 initially but I'll be writing code for a 16f1827/47 with a hardware EUART later on.

DavidAlfa:
First try toggling  a led every onebitdelay *  baudrate (9600, whatever) and see if you get anything close to 1 second.
What warnings did you receive?

djsb:
Here are the warnings

--- Code: ---make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'F:/XC8_WORK/XC8_16F819/03_RS232.X'
make  -f nbproject/Makefile-default.mk dist/default/production/03_RS232.X.production.hex
make[2]: Entering directory 'F:/XC8_WORK/XC8_16F819/03_RS232.X'
"C:\Program Files\Microchip\xc8\v2.40\bin\xc8-cc.exe"  -mcpu=16F819 -c   -mdfp="C:/Program Files/Microchip/MPLABX/v6.05/packs/Microchip/PIC16Fxxx_DFP/1.3.42/xc8"  -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -DXPRJ_default=default  -msummary=-psect,-class,+mem,-hex,-file  -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -mdefault-config-bits   -std=c99 -gdwarf-3 -mstack=compiled:auto:auto     -o build/default/production/Main.p1 Main.c
"C:\Program Files\Microchip\xc8\v2.40\bin\xc8-cc.exe"  -mcpu=16F819 -c   -mdfp="C:/Program Files/Microchip/MPLABX/v6.05/packs/Microchip/PIC16Fxxx_DFP/1.3.42/xc8"  -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -DXPRJ_default=default  -msummary=-psect,-class,+mem,-hex,-file  -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -mdefault-config-bits   -std=c99 -gdwarf-3 -mstack=compiled:auto:auto     -o build/default/production/sw_uart.p1 sw_uart.c
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
Main.c:106:18: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
        letter = n;
               ~ ^
Main.c:108:26: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; take the address with & [-Wint-conversion]
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
                         ^~~~~~
                         &
./sw_uart.h:44:29: note: passing argument to parameter 'text' here
void SUART_Write_Text(char *text);
                            ^
Main.c:114:18: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
        letter = i;
               ~ ^
Main.c:116:26: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; take the address with & [-Wint-conversion]
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
                         ^~~~~~
                         &
./sw_uart.h:44:29: note: passing argument to parameter 'text' here
void SUART_Write_Text(char *text);
                            ^
Main.c:121:18: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
        letter = n;
               ~ ^
Main.c:123:26: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; take the address with & [-Wint-conversion]
        SUART_Write_Text(letter);// SPACE for testing. Measure bit time on a scope.
                         ^~~~~~
                         &
./sw_uart.h:44:29: note: passing argument to parameter 'text' here
void SUART_Write_Text(char *text);
                            ^
6 warnings generated.
"C:\Program Files\Microchip\xc8\v2.40\bin\xc8-cc.exe"  -mcpu=16F819 -Wl,-Map=dist/default/production/03_RS232.X.production.map  -DXPRJ_default=default  -Wl,--defsym=__MPLAB_BUILD=1   -mdfp="C:/Program Files/Microchip/MPLABX/v6.05/packs/Microchip/PIC16Fxxx_DFP/1.3.42/xc8"  -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -msummary=-psect,-class,+mem,-hex,-file  -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -mdefault-config-bits -std=c99 -gdwarf-3 -mstack=compiled:auto:auto      -Wl,--memorysummary,dist/default/production/memoryfile.xml -o dist/default/production/03_RS232.X.production.elf  build/default/production/Main.p1 build/default/production/sw_uart.p1     
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
sw_uart.c:45:: warning: (520) function "_SUART_Receive" is never called
sw_uart.c:150:: warning: (520) function "_SUART_Read_Text" is never called
sw_uart.c:167:: warning: (520) function "_SUART_Write_Char" is never called
sw_uart.c:154:: warning: (1498) pointer (SUART_Read_Text@Output) in expression may have no targets

Memory Summary:
    Program space        used    CAh (   202) of   800h words   (  9.9%)
    Data space           used    11h (    17) of   100h bytes   (  6.6%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     1h (     1) of     1h word    (100.0%)
    ID Location space    used     4h (     4) of     4h bytes   (100.0%)

make[2]: Leaving directory 'F:/XC8_WORK/XC8_16F819/03_RS232.X'
make[1]: Leaving directory 'F:/XC8_WORK/XC8_16F819/03_RS232.X'

BUILD SUCCESSFUL (total time: 12s)
Loading code from F:/XC8_WORK/XC8_16F819/03_RS232.X/dist/default/production/03_RS232.X.production.hex...
Program loaded with pack,PIC16Fxxx_DFP,1.3.42,Microchip
Loading completed



--- End code ---

The bit time (onebitdelay) should be 104.16 microsececonds. I will try this test (onebitdelay * 9600) (which should have been obvious to me) next week. Thanks.

DavidAlfa:
That warning means something  ;).
SUART_Write_Text() expects a pointer to a string, you're loading "letter" to it.

First try something more simple (main.c loop):

--- Code: ---while(1){
    SUART_Write_Text("Hello!\r\n");
    __delay_ms(1000);
}

--- End code ---


Then fix your code by replacing SUART_Write_Text(letter) with SUART_Write_Char(letter)

djsb:
Thanks. I will try that. Just for clarification in


--- Code: ---void SUART_Write_Char(char a)
{
    SUART_Transmit(a - 128);
}


--- End code ---

In the line


--- Code: ---SUART_Transmit(a - 128);

--- End code ---

What does (a - 128) parameter do?

My for loops already pass the correct range of values to the function. Maybe I need to change the parameter that I pass to SUART_Transmit? Thanks.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod