I've configured the chip and am able to program and run it. I can see this due to a couple LEDs I'm using on PortC. I've altered the program and see the result in the blink rate/pattern of the LEDs.
I then connected up the serial driver chip with to the controller and the host PC and gave it a try. I'm able to transmit from the controller to the host PC and the text I send shows up on the terminal window. However, I'm not receiving any characters on the microcontroller from the host PC.
I've gone through the following several times, but can't find my error:
- The schematic for the circuit, which you can see here: http://www.mehconsulting.com/PIC/PIC16F690.pdf
- The component layout on the solderless breadboard (I don't know how to show you this...)
- The data sheet sections on configuring the chip for the oscillator, baud rate generator, etc.
- The data sheet sections on the use of the USART
The code includes an interrupt service routine "void interrupt isrRoutine(void) { ...}" which doesn't appear to be getting called when I send characters to the controller from the host PC. I've added a check for the RCIF (Receive Interrupt Flag) to the main loop, but never see it get set.
I was wondering if the TXSTA and RCSTA registers suffer from the read-modify-write issue and if perhaps my configuration bits are not getting set as I've requested, but all the examples I can find which show how to set up the configuration does it the way I'm doing it.
I've tried to trim the code down as much as possible. Can someone please let me know what they think I'm missing?
First: main.h
- Code: Select all
#ifndef MAIN_H
#define MAIN_H
#include <htc.h>
typedef unsigned char uint8_t;
#define true 1
#define false 0
#define EQU ==
// This is required to use the __delay_us(...) or __delay_ms(...) in pic.h:
#define _XTAL_FREQ 8000000
// General
#define _CONCAT(a,b) a##b
#define PORT(x) _CONCAT(PORT,x)
#define TRIS(x) _CONCAT(TRIS,x)
// Indicator LED
#define ALARM_STATUS_RED 0
#define ALARM_STATUS_GREEN 1
#define ACTIVITY_BLIP_TIME 1500
#define ALARM_GREEN_PORT C
#define ALARM_RED_PORT C
#define ACTIVITY_PORT C
#define ALARM_GREEN_POS 0
#define ALARM_RED_POS 1
#define ACTIVITY_POS 2
#define ALARM_GREEN_PORT_TRIS TRIS(ALARM_GREEN_PORT)
#define ALARM_RED_PORT_TRIS TRIS(ALARM_RED_PORT)
#define ACTIVITY_PORT_TRIS TRIS(ACTIVITY_PORT)
#define ALARM_GREEN_PORT_DATA PORT(ALARM_GREEN_PORT)
#define ALARM_RED_PORT_DATA PORT(ALARM_RED_PORT)
#define ACTIVITY_PORT_DATA PORT(ACTIVITY_PORT)
#define SET_ALARM_GREEN_PORT_OUTPUT() ALARM_GREEN_PORT_TRIS &= ( ~ ( 1 << ALARM_GREEN_POS ) ); // Set the pin as an output
#define SET_ALARM_RED_PORT_OUTPUT() ALARM_RED_PORT_TRIS &= ( ~ ( 1 << ALARM_RED_POS ) ); // Set the pin as an output
#define SET_ACTIVITY_PORT_OUTPUT() ACTIVITY_PORT_TRIS &= ( ~ ( 1 << ACTIVITY_POS ) ); // Set the pin as an output
#define ALARM_GREEN_PORT_HIGH() (ALARM_GREEN_PORT_DATA |= (1 << ALARM_GREEN_POS)) // Set the pin
#define ALARM_GREEN_PORT_LOW() (ALARM_GREEN_PORT_DATA &= ( ~ (1 << ALARM_GREEN_POS))) // Clear the pin
#define ALARM_RED_PORT_HIGH() (ALARM_RED_PORT_DATA |= (1 << ALARM_RED_POS)) // Set the pin
#define ALARM_RED_PORT_LOW() (ALARM_RED_PORT_DATA &= ( ~ (1 << ALARM_RED_POS))) // Clear the pin
#define ACTIVITY_PORT_HIGH() (ACTIVITY_PORT_DATA |= (1 << ACTIVITY_POS)) // Set the pin
#define ACTIVITY_PORT_LOW() (ACTIVITY_PORT_DATA &= ( ~ (1 << ACTIVITY_POS))) // Clear the pin
#endif
Next, is main.c:
- Code: Select all
/*
* This is a simple project for use with the PIC18F4520 chip, internal oscillator
* set to run at 8MHz.
*
* The purpose of this project is to talk to the PC via the ESUART utilizing
* interrupts for the receiver and to talk to a 2x16 LCD.
*/
asm("LIST c=128");
#include "main.h"
#include <stdio.h>
__CONFIG( FCMEN_OFF & IESO_OFF & BOREN_OFF & CPD_OFF & MCLRE_ON & PWRTE_OFF & WDTE_OFF & FOSC_INTRCIO );
void USARTInit ( )
{
// Configure the EUSART:
// 4MHz Fosc at 9600 baud = SPRG value of 207 (0xCF))
// SPBRGH = 0x00;
// SPBRG = 0xCF;
SPBRGH = 0x00;
SPBRG = 0xCF;
BRGH = 1; // TXSTA: Enable high-speed baud rate
BRG16 = 1; // Baudcon: 16-bit Baud Rate Register Enable bit
SYNC = 0; // TXSTA: Select Asynchronous mode
SPEN = 1; // RCSTA: Serial Port Enable bit
TX9 = 0; // TXSTA: Select 8-bit data
TXEN = 1; // TXSTA: Transmitter Enable
RX9 = 0; // RCSTA: Select 8-bit data
CREN = 1; // RCSTA: Continuous receive enable bit
}
void USARTWriteByte ( char ch )
{
if ( OERR == 0x1 || FERR == 0x1 )
{
SPEN = 0x0;
TXEN = 0x0;
SPEN = 0x1;
TXEN = 0x1;
}
// Wait for TXREG Buffer to become available
while ( !TXIF )
;
// Write data
TXREG = ch;
}
void USARTWriteString ( const char *str )
{
while ( ( *str ) != '\0' )
{
//Wait for TXREG Buffer to become available
while ( !TXIF )
;
//Write data
TXREG = ( *str );
//Next goto char
str++;
}
}
void USARTWriteLine ( const char *ln )
{
USARTWriteString( ln );
USARTWriteString( "\r\n" );
}
// Eclipse shows this as a syntax error because it doesn't know about
// the "interrupt" tag:
void interrupt
isrRoutine(void) {
// This is the interrupt service routine
// First, check the EUSART Receive Interrupt Flag
if (RCIF) {
USARTWriteLine("Found RCIF");
// This is an EUSART Receiver interrupt
if (OERR EQU 0x1 || FERR EQU 0x1) {
// If we had an error, reset the USART and bail.
SPEN = 0x0; // Serial Port Enable OFF
CREN = 0x0; // Continuous Receive Enable OFF
SPEN = 0x1; // Serial Port Enable ON
CREN = 0x1; // Continuous Receive Enable ON
} else {
// Receive the character(s)
while (RCIF) {
uint8_t currentChar = RCREG;
if ( currentChar EQU 0x0A ) {
USARTWriteString( "\r\n" );
} else if ( currentChar EQU 0x0D ) {
USARTWriteString( "\r\n" );
} else {
USARTWriteByte( currentChar );
}
}
}
}
// ... continue to check for other interrupts. There may be more than one source.
} // void interrupt isrRoutine( void )
void main() {
unsigned char latC = 0b00000000;
unsigned char activity = true;
unsigned long activityCount = 0;
unsigned char activityBlip = 0;
unsigned long cycleCount = 0;
unsigned char alarmStatus = ALARM_STATUS_RED;
// IRFC<2:0> = 111 - 8MHz internal oscillator
// OSTS = 0 - Device is running from the internal oscillator status bit (Read only)
// HTS = 0 - HFINTOSC status bit (read only)
// LTS = 0 - LFINTOSC stable bit (read only)
// SCS = 1 - Internal oscillator used for system clock
OSCCON = 0b1110001;
while ( OSTS EQU 1 ) {
; // Wait until the processor is running from the internal oscillator.
}
while ( HTS EQU 0 ) {
; // Wait for the HFINTOSC to become stable at the new speed.
}
__delay_ms(50); // Delay the startup so we don't stumble during programming.
//Initialize the USART
USARTInit();
__delay_ms(50);
// Enable interrupts, used by the USART Receiver
PEIE = 1; // Enable peripheral interrupts
RCIE = 1; // Enable USART Receiver interrupts
RCIF = 0; // Clear the USART Receiver interrupt flag
GIE = 1; // Enable global interrupts
__delay_ms(50);
USARTWriteLine("\r\nReady");
TRISC = 0b00000000;
while (true) {
if ( ++cycleCount > 15000 ) {
cycleCount = 0;
if ( alarmStatus EQU ALARM_STATUS_RED ) {
latC |= (1 << ALARM_GREEN_POS); // Drive ALARM_GREEN high
latC &= ( ~ ( 1 << ALARM_RED_POS) ); // Drive ALARM_RED low
alarmStatus = ALARM_STATUS_GREEN;
} else {
latC |= (1 << ALARM_RED_POS); // Drive ALARM_RED high
latC &= ( ~ ( 1 << ALARM_GREEN_POS) ); // Drive ALARM_GREEN low
alarmStatus = ALARM_STATUS_RED;
activityBlip = true;
// USARTWriteLine("Blip");
}
}
if ( activityBlip EQU true ) {
activityBlip = false;
latC |= (1 << ACTIVITY_POS); // Drive ACTIVITY high
activityCount = 0;
activity = true;
}
if ( activity EQU true ) {
if ( ++activityCount EQU ACTIVITY_BLIP_TIME ) {
latC &= ( ~ ( 1 << ACTIVITY_POS) ); // Drive ACTIVITY low
activity = false;
activityCount = 0;
}
}
PORTC = latC;
// This is just a check to see if we've received a character from the serial port
if ( RCIF ) {
USARTWriteLine( "Main loop: found RCIF set.");
}
}
} // main()
Thanks,