http://saeedsolutions.blogspot.de/2012/ ... nging.html
And I tested it myself. It is working.
To be able to post all the code here I combined all the nice spread subroutines and headers in a single C file below:
- Code: Select all
#include <xc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
#define Baudrate 1200 //bps
#define OneBitDelay (1000000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX GP1 // UART RX pin
#define UART_TX GP0 // UART TX pin
#define UART_RX_DIR TRISIO1 // UART RX pin direction register
#define UART_TX_DIR TRISIO0 // UART TX pin direction register
//Function Declarations
void InitSoftUART(void);
unsigned char UART_Receive(void);
void UART_Transmit(const char);
__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & CP_OFF & CPD_OFF);
void main()
{
unsigned char ch = 0;
ANSEL = 0x00; // Set ports as digital I/O, not analog input
ADCON0 = 0x00; // Shut off the A/D Converter
CMCON = 0x07; // Shut off the Comparator
VRCON = 0x00; // Shut off the Voltage Reference
//TRISIO = 0x08; // GP3 input, rest all output
GPIO = 0x00; // Make all pins 0
InitSoftUART(); // Intialize Soft UART
while(1)
{
ch = UART_Receive(); // Receive a character from UART
UART_Transmit(ch); // Echo back that character
}
}
void InitSoftUART(void) // Initialize UART pins to proper values
{
UART_TX = 1; // TX pin is high in idle state
UART_RX_DIR = 1; // Input
UART_TX_DIR = 0; // Output
}
unsigned char UART_Receive(void)
{
// Pin Configurations
// GP1 is UART RX Pin
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;
}
}
void UART_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);
}
Then I decided to try it on PIC10F322. The code was modified with differenr name for pins and regfisters as below:
- Code: Select all
#include <xc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
#define Baudrate 1200 //bps
#define OneBitDelay (1000000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX RA1 // UART RX pin
#define UART_TX RA0 // UART TX pin
#define UART_RX_DIR TRISA1 // UART RX pin direction register
#define UART_TX_DIR TRISA0 // UART TX pin direction register
//Function Declarations
void InitSoftUART(void);
unsigned char UART_Receive(void);
void UART_Transmit(const char);
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF &
WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void main()
{
unsigned char ch = 0;
ANSELA = 0x00; // Set ports as digital I/O, not analog input
ADCON = 0x00; // Shut off the A/D Converter
FVRCON = 0x00; // Shut off the Voltage Reference
PORTA = 0x00; // Make all pins 0
InitSoftUART(); // Intialize Soft UART
InitSoftUART(); // Intialize Soft UART
while(1)
{
ch = UART_Receive(); // Receive a character from UART
UART_Transmit(ch); // Echo back that character
}
}
void InitSoftUART(void) // Initialize UART pins to proper values
{
UART_TX = 1; // TX pin is high in idle state
UART_RX_DIR = 1; // Input
UART_TX_DIR = 0; // Output
}
unsigned char UART_Receive(void)
{
// Pin Configurations
// GP1 is UART RX Pin
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;
}
}
void UART_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);
}
In case the code os too long and cannot be seen well above, then I uploaded it one more time here as txt:
UART 12F675:
https://drive.google.com/open?id=0BwXmK ... kZfS0dnQ2M
UART 10F322:
https://drive.google.com/open?id=0BwXmK ... S04c1BGR1U
Unfortunately is not working with Pic10F322. It sends out only one long “0” as a series of 8bits all 0 logic.
Any help to debug and see what is wrong with it is appreciated.