Electronics > Microcontrollers
XC8 Soft UART on PIC16F819-Help please
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
Go to full version