Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problems running basic UART code on PIC18F25K80

Status
Not open for further replies.

ARQuattr

Member level 2
Joined
Sep 7, 2010
Messages
52
Helped
11
Reputation
22
Reaction score
11
Trophy points
1,288
Activity points
1,880
I have some basic code I'm trying to get working on a PIC18F25K80, which I've had running on various PIC16 variants with no issues. There is a function "writeStringToUART" that is intended to send out strings via UART2. This function gives no output (I'm watching the TX line on a logic analyzer), although when I step through it in the debugger it appears to work properly and I can see the correct characters supposedly being sent.

I also have a direct TXREG2 = 0xAA and that comes out of the TX line no problem. That would seem to suggest a compiler or function call issue. I tried multiple variations on the code (checking TRMT instead of TX2IF, checking before setting TXREG2 or after, using pointers referencing of the string, or array notation), and I got the same result - writeStringToUART doesn't send characters while just setting TXREG2 directly does. As I said the writeStringToUART has been used on previous projects (after some register name changes) with no problems. One difference is that I just installed MPLABX v1.9 while before I was using MPLAB 8. Also the compiler now is XC8 v1.2 and before it was HiTechC 9.82.

One other thing I haven't figured which might be related is that I'm setting OSCCON to 0x30 to get 4MHz, when I feel it should be 0x50. It's running 4x as fast, but as far as I can tell I don't have any PLL or scalers enabled.

I appreciate any thoughts you have.

Code:
void initPorts(void) {
    //Set oscillator options
    OSCCON = 0x30;              //4MHz (this is not correct - it should be 0x50 for 4MHz - why?)

    //Analog configuration
    ANCON0 = 0b00010000;        //AIN4 is used as analog input
    ADCON1 = 0b00000111;        //AIN8,9, and 10 are used as analog input
    ADCON2 = 0xBC;              //20 TAD, Fosc/4
    ADON = 1;                   //enable ADC

    //Digital configurations
    PORTA = 0b00000000;         // Initial state of PORTA
    TRISA = 0b11111111;         // Set PORTA pin directions: all input

    PORTB = 0b01001000;         // Initial state of PORTB (driver and receiver disabled, TX high, other outputs off)
    TRISB = 0b10010011;         // Set PORTB pin directions: RB2, RB3, RB5, RB6 output, all others input

    PORTC = 0b00000000;         // Initial state of PORTC (turn LEDs, outputs off)
    TRISC = 0b11100000;         // Set PORTC pin directions: RC0-RC4 output, RC5-RC7 input
}

void initComms()
{
    /* Serial port initialization */
    TXSTA2bits.BRGH = 1;
    TXSTA2bits.SYNC = 0;
    SPBRGH2 = 0;
    SPBRG2 = 25;                    //((FCY/16)/BAUD) - 1; // set baud to 9600  FCY=4000000
    BAUDCON2 = 0x08;                //BRGH16 = 1

    TXSTA2bits.TXEN = 1;            //Enables transmitter
    RCSTA2bits.CREN = 1;            //Enables receiver
    RCSTA2bits.SPEN = 1;            //Enable UART
}

void writeStringToUART (const char* msg)
{
    while (msg[0] != 0)    {
        while (PIR3bits.TX2IF == 0) {}
        TXREG2 = msg[0];
        msg++;
    }
}
 
void main(void)
{
    /***Initialization***/
    initPorts();        // Initialize ports to startup state
    initComms();        // Initialize the serial port
 
    while(1) {
        writeStringToUART ("test\n");
        DelayMs(250);

        while (PIR3bits.TX2IF == 0) {}
        TXREG2 = 0xAA;
        DelayMs(250);
        }
}
 

Are you sure you are writing a string to the UART? It looks like all you do is send a single character and only then if it isn't a null. Shouldn't your 'msg++' be selecting an index to the string rather than using the constant zero.

Brian.
 
Usually UART will be on PORTC. Rx = RC7 and Tx = RC6. You should make Tx pin output and Rx pin input pin.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//Fosc = 4 MHz
 
TXSTA2bits.CSRC = 0;
TXSTA2bits.TX9 = 0;
TXSTA2bits.TXEN = 1;
TXSTA2bits.SYNC = 0;
TXSTA2bits.SENDB = 0;
TXSTA2bits.BRGH = 1;
TXSTA2bits.TRMT = 1;
TXSTA2bits.TX9D = 0;
 
RCSTA2bits.SPEN = 1;
RCSTA2bits.RX9 = 0;
RCSTA2bits.SREN = 0;
RCSTA2bits.CREN  = 0;
RCSTA2bits.ADDEN = 0;
RCSTA2bits.FERR = 0;
RCSTA2bits.OERR = 0;
RCSTA2bits.RX9D = 0;
 
BAUDCON2bits.ABDOVF = 0;
BAUDCON2bits.RCIDL = 1;
BAUDCON2bits.RXDTP = 0;
BAUDCON2bits.TXCKP = 0;
BAUDCON2bits.BRG16 = 1;
BAUDCON2bits.WUE = 0;
BAUDCON2bits.ABDEN = 0;
 
SPBRGH2 = 0;
SPBRG = 1.3;
 
void writeStringToUART (const char *msg)
{
    while(*msg)    {
        while(PIR3bits.TX2IF == 0);
        TXREG2 = *msg++;        
    }
}

 
Last edited:

Are you sure you are writing a string to the UART? It looks like all you do is send a single character and only then if it isn't a null. Shouldn't your 'msg++' be selecting an index to the string rather than using the constant zero.

Brian.

Thank you Brian for your reply. msg is a pointer to the first byte of the array, so I'm just indexing to the next byte, then when I use msg[0] again it's pointing to the next byte. I tried many variations, including using an index variable that incremented, leaving msg alone, but I got the same results.

- - - Updated - - -

Thank you Jayanth for your reply. On the 18F25K80, EUSART2 pins are RB6 and RB7 and I set the TRISB bits accordingly. Yes UART1 is RC6 and 7, but I'm currently trying to get UART2 working. I haven't tried UART1 so I'm not sure if the same code works there (the board design doesn't make it that easy to access those pins).

I will try the code you sent. BTW, what does the notation SPBRG = 1.3; do?

- - - Updated - - -

Jayanth, I replaced the writeStringToUART function with yours and replaced the contents of initComms with your initialization code. The baud rate shot up to 250kbps (I think it still needs to set SPBRG2), but otherwise I got the same output - 0xAA comes out fine, but nothing else.

I'm wondering if the other pin functions for RC6 and RC7 are interfering, in particular I was concerned about the programmer pins since I'm using a PICkit3 to program the board.

- - - Updated - - -

This is very peculiar, and frustrating. I added the code from the writeStringToUART function into the main function to make sure it wasn't some stack issue or whatever. I couldn't use it exactly because it wouldn't let me increment the pointer that way so I used an array index, but still it didn't print anything. What is really strange (to me) is that after removing the delays (just out of desperation and lack of better ideas) I found that there are no delays between the 0xAA outputs. I had assumed that there was some time being wasted 'writing' those characters to the UART but they just weren't seeing the pin, but now it appears that it skips right through that quickly (less than the time it takes to send a single byte, ~1.04ms).

Below is what the code looks like now, and the output is only 0xAA constantly, with no delays.

Code:
char newmsg[80], i;

initPorts();        // Initialize ports to startup state
initComms();		// Initialize the serial port

while(1){
        writeStringToUART ("test\n");
//        DelayMs(250);


        sprintf (newmsg, "Address = %d\n", 1234);
        i = 0;
        while (newmsg[i] != 0)    {
            while (PIR3bits.TX2IF == 0) {}
            TXREG2 = newmsg[i++];
        }

//        DelayMs(250);

        while (PIR3bits.TX2IF == 0) {}
        TXREG2 = 0xAA;
}
 

So I did some further troubleshooting and I'm more convinced now that this actually is not a UART problem, but a compiler issue, specifically in dealing with strings. The writeStringToUART function is actually working fine, but only if I declare a string and pass the string variable. If I try to pass a constant string as the argument, or try to use sprintf to write the string, it doesn't work. They just appear as NULLs so are not written to the UART. The output of code below is "This works" printe repeatedly. The "This doesn't" and "Nor this" strings don't come out. What's even stranger is that if I step through the code, everything appears to work perfectly. The strings are correct and the writeStringToUART function iterates through each character of all three strings properly.

I normally use this function on other devices for printing messages, but only in the two forms shown here that don't work. In particular I find it useful to use sprintf to format strings with variable values.

Does the extended instruction set have anything to do with this? I've never used a device with this before. I have it disabled because otherwise MPLAB gives an error and won't program the chip. Are there any other CONFIG bits or compiler options I should check?

Code:
void main ()
{
    char msg1[80] = "This works\n";
    char msg3[80];

    /***Initialization***/
    initPorts();              // Initialize ports to startup state
    initComms();		// Initialize the serial port

    while(1) {
        writeStringToUART (msg1);
        writeStringToUART ("This doesn't\n");
        sprintf (msg3, "Nor this\n");
        writeStringToUART (msg3);
        DelayMs(2);
    }
}
 

Then the problem is not with UART but some other issue. Post full code. Maybe you have not included some header file which is needed for handling string operations. See if enabling GIE and PEIE solves the problem.
 

OSCON, OSCON2, etc... have to be configured properly.

I believe I set all the oscillator control registers and config bits properly, although I get four times the frequency I expect from the OSCCON setting. I'm not sure if this is related to my UART problem.
 

Post code related to Oscillator settings. Are you using INTRC OSC or EXT XT OSC? What is Fosc? The SPBRGx values I gave is for 4 MHz Fosc.

Page 333 of datasheet tells this.

For EUSART2:
- SPEN (RCSTA2<7>) must be set (= 1)
- TRISx<x> must be set (= 1)
- For Asynchronous and Synchronous Master
modes, TRISx<x> must be cleared (= 0)



PIR1.TXB2IF nd othe transmit buffers enable
PIE3.TX1IE
PIE3.RC1IE
PIR5.TXB2IE and othe transmit buffers enable
 
Last edited:

I tried setting GIE and PEIE but it didn't change anything. I am posting the full code here:

main.c

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include "Main.h"
//=============================================================================
// Filename: Main.c
//=============================================================================
// Revision: 1.0
//
//=============================================================================
 
//**************************************************************************************** 
//                    CONFIGURATION BITS PIC18F25K80
//**************************************************************************************** 
 
// Configuration register
 
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = DIG    // SOSC Power Selection and mode Configuration bits (Digital (SCLKI) mode)
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
 
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
 
// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS  // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
 
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)
 
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = OFF      // Master Clear Enable (MCLR Disabled, RG5 Enabled)
 
// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)
 
// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled)
 
// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)
 
// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-03FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 04000-07FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 08000-0BFFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 0C000-0FFFF (Disabled)
 
// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)
 
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-03FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 04000-07FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 08000-0BFFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 0C000-0FFFF (Disabled)
 
// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)
 
 
void main(void)
{
    unsigned char address = 0;
    char msg1[80] = "This works\n";
    char msg2[80];
 
    /***Initialization***/
    //SWDTEN = 1;       // Enable the watchdog
    initPorts();        // Initialize ports to startup state
    initComms();        // Initialize the serial port
 
    GIE = 1;
    PEIE = 1;
   
    outputsOff();
    testLEDs();
 
    writeStringToUART ("\nIPRCB, v1.0, Sep 2013\n");
 
    //Read Address setting
    address = readAddress();
    sprintf (msg, "Address = %d\n", address);
    writeStringToUART (msg);
 
    while(1){
        writeStringToUART (msg1);
        writeStringToUART ("This doesn't\n");
        sprintf (msg2, "Nor this\n");
        writeStringToUART (msg2);
        DelayMs(2);
    }
 
 
 
    //Main state machine
    while (1) {
        switch (state) {
        case STATE_BOOT:
            state = STATE_MONITOR;
            break;
 
        case STATE_MONITOR:
 
            //Take analog readings
            readSensor(SENSOR_A);
            readSensor(SENSOR_B);
 
            break;
        }
 
        DelayMs(POLLING_DELAY);
    }
}
 
 
void outputsOff()
{
    OUTPUT_A = OFF;
    OUTPUT_B = OFF;
 
    LOW_LED_A = OFF;
    HIGH_LED_A = OFF;
    LOW_LED_B = OFF;
    HIGH_LED_B = OFF;
}
 
void testLEDs()
{
    //Flash all LEDs to show the chip reset
    LOW_LED_A = ON;
    DelayMs(250);
    LOW_LED_A = OFF;
    HIGH_LED_A = ON;
    DelayMs(250);
    HIGH_LED_A = OFF;
 
    LOW_LED_B = ON;
    DelayMs(250);
    LOW_LED_B = OFF;
    HIGH_LED_B = ON;
    DelayMs(250);
    HIGH_LED_B = OFF;
}
 
void readSensor(unsigned char sensor)
{
    static unsigned int sensorReading[NUM_SENSORS];
    static unsigned int thresholdReading[NUM_SENSORS];
 
    static unsigned int sensorData[NUM_SENSORS][SENSOR_DATA_SIZE] = {0};
    static unsigned int thresholdData[NUM_SENSORS][THRESHOLD_DATA_SIZE] = {0};
    static unsigned int sensorDataIndex[NUM_SENSORS] = {0};
    static unsigned int thresholdDataIndex[NUM_SENSORS] = {0};
 
    unsigned int index;
    unsigned long accumulator = 0;
 
    unsigned int sensorAverage[NUM_SENSORS];
    unsigned int thresholdAverage[NUM_SENSORS];
 
 
    sensorReading[sensor] = readVoltage(SENSOR_CHANNEL(sensor));
    thresholdReading[sensor] = readVoltage(THRESHOLD_CHANNEL(sensor));
 
    //Update LEDs with direct comparison result (pre-filtering)
    if (sensorReading[sensor] < thresholdReading[sensor]) {
        output(sensor, OUTPUT_TYPE_LOW_LED, ON);
        output(sensor, OUTPUT_TYPE_HIGH_LED, OFF);
    } else {
        output(sensor, OUTPUT_TYPE_LOW_LED, OFF);
        output(sensor, OUTPUT_TYPE_HIGH_LED, ON);
    }
 
    //Add new readings to data arrays
    sensorData[sensor][sensorDataIndex[sensor]++] = sensorReading[sensor];
    if (sensorDataIndex[sensor] == SENSOR_DATA_SIZE) {
        sensorDataIndex[sensor] = 0;
    }
 
    thresholdData[sensor][thresholdDataIndex[sensor]++] = thresholdReading[sensor];
    if (thresholdDataIndex[sensor] == THRESHOLD_DATA_SIZE) {
        thresholdDataIndex[sensor] = 0;
    }
 
    //Recalculate moving averages
    for (index = 0; index < SENSOR_DATA_SIZE; index++) {
        accumulator += sensorData[sensor][index];
    }
    sensorAverage[sensor] = accumulator / SENSOR_DATA_SIZE;
 
    for (index = 0; index < THRESHOLD_DATA_SIZE; index++) {
        accumulator += thresholdData[sensor][index];
    }
    thresholdAverage[sensor] = accumulator / THRESHOLD_DATA_SIZE;
 
//    sprintf (msg, "Sensor %d: average = %d, threshold = %d, ", sensor, sensorAverage[sensor], thresholdAverage[sensor]);
    writeStringToUART (msg);
 
    //Update outputs
    if (sensorAverage[sensor] < thresholdAverage[sensor]) {
        output(sensor, OUTPUT_TYPE_SSR, ON);
        writeStringToUART ("output ON\n");
    } else {
        output(sensor, OUTPUT_TYPE_SSR, OFF);
        writeStringToUART ("output OFF\n");
    }
}
 
unsigned int readVoltage(unsigned char channel) {
    unsigned int result;
 
    ADCON0bits.CHS = channel; //set channel number
    DelayMs(20); //allow channel change settling time
    GO_nDONE = 1; //start conversion
    while (GO_nDONE) //wait for conversion complete
        CLRWDT(); //Feed the dog
 
    result = ADRESL | (ADRESH & 0x0F);
    return (result * ADC_SCALING_FACTOR);
}
 
 
void output(unsigned char channel, unsigned char outputType, unsigned char onOff)
{
    if (channel == SENSOR_A) {
        switch (outputType) {
        case OUTPUT_TYPE_LOW_LED:
            LOW_LED_A = onOff;
            break;
        case OUTPUT_TYPE_HIGH_LED:
            HIGH_LED_A = onOff;
            break;
        case OUTPUT_TYPE_SSR:
            OUTPUT_A = onOff;
            break;
        }
    } else {
        switch (outputType) {
        case OUTPUT_TYPE_LOW_LED:
            LOW_LED_B = onOff;
            break;
        case OUTPUT_TYPE_HIGH_LED:
            HIGH_LED_B = onOff;
            break;
        case OUTPUT_TYPE_SSR:
            OUTPUT_B = onOff;
            break;
        }
    }
}
 
unsigned char readAddress()
{
    return !nADDR3 << 3 | !nADDR2 << 2 | !nADDR2 << 1 | !nADDR0;
}



main.h

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "Ports.h"
#include "delay.h"
#include "usart.h"
 
 
// I/O designations
//Pin 2 (RA0/AN0) - Address bit 0 (inverted logic input) / Analog Vref input
//Pin 3 (RA1) - Address bit 1 (inverted logic input)
//Pin 4 (RA2) - Address bit 2 (inverted logic input)
//Pin 5 (RA3) - Address bit 3 (inverted logic input)
//Pin 7 (AN4) - Threshold B analog input
//Pin 11 (RC0) - High LED B
//Pin 12 (RC1) - Low LED B
//Pin 13 (RC2) - Output B
//Pin 14 (RC3) - High LED A
//Pin 15 (RC4) - Low LED A
//Pin 16 (RC5) - Spare
//Pin 17 (TX1) - Bus TX
//Pin 18 (RX1) - Bus RX
//Pin 21 (AN10) - Sensor A analog input (scaled down 3:1)
//Pin 22 (AN8) - Threshold A analog input
//Pin 23 (RB2) - Bus DE (driver enable output)
//Pin 24 (RB3) - Bus RE (inverted logic) (receiver enable output)
//Pin 25 (AN9) - Sensor B analog input (scaled down 3:1)
//Pin 26 (RB5) - Output A
//Pin 27 (TX2) - Debug UART TX
//Pin 28 (RX2) - Debug UART RX
 
#define nADDR0                          RA0
#define nADDR1                          RA1
#define nADDR2                          RA2
#define nADDR3                          RA3
 
#define VREF_CHANNEL                    0
 
#define SENSOR_A_CHANNEL                10
#define THRESHOLD_A_CHANNEL             8
#define LOW_LED_A                       RC4
#define HIGH_LED_A                      RC3
#define OUTPUT_A                        RB5
 
#define SENSOR_B_CHANNEL                9
#define THRESHOLD_B_CHANNEL             4
#define LOW_LED_B                       RC1
#define HIGH_LED_B                      RC0
#define OUTPUT_B                        RC2
 
#define BUS_DE                          RB2
#define nBUS_RE                         RB3
 
#define SPARE                           RC5
 
 
#define ADC_SCALING_FACTOR              36
#define POLLING_DELAY                   40          //ms to wait between state machine cycles
 
#define TRUE                1
#define FALSE               0
 
#define ON              1
#define OFF                 0
 
 
// States for the Main State Machine
enum {
    /* Operational states */
    STATE_BOOT, STATE_MONITOR
};
 
#define NUM_SENSORS                     2
#define SENSOR_DATA_SIZE                100
#define THRESHOLD_DATA_SIZE             20
enum {
    SENSOR_A, SENSOR_B
};
 
#define SENSOR_CHANNEL(s)               (s==SENSOR_A?SENSOR_A_CHANNEL:SENSOR_B_CHANNEL)
#define THRESHOLD_CHANNEL(s)            (s==SENSOR_A?THRESHOLD_A_CHANNEL:THRESHOLD_B_CHANNEL)
 
enum {
    OUTPUT_TYPE_LOW_LED, OUTPUT_TYPE_HIGH_LED, OUTPUT_TYPE_SSR
};
 
// Global variables
unsigned char state = STATE_BOOT;
unsigned int delay_ticks = 0;
char msg[80];
 
// Function prototypes
void outputsOff();
void testLEDs();
void readSensor(unsigned char sensor);
unsigned int readVoltage(unsigned char channel);
void output(unsigned char channel, unsigned char outputType, unsigned char onOff);
unsigned char readAddress();




ports.c

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "Main.h"
//=============================================================================
// Filename: Ports.c
//=============================================================================
 
void initPorts(void) {
 
 
    //Set oscillator options
    OSCCON = 0x30;              //4MHz
 
    //Analog configuration
    ANCON0 = 0b00010000;        //AIN4 is used as analog input
    ADCON1 = 0b00000111;        //AIN8,9, and 10 are used as analog input
    ADCON2 = 0xBC;              //20 TAD, Fosc/4
    ADON = 1;                   //enable ADC
 
    //Digital configurations
    PORTA = 0b00000000;         // Initial state of PORTA
    TRISA = 0b11111111;         // Set PORTA pin directions: all input
 
    PORTB = 0b01001000;         // Initial state of PORTB (driver and receiver disabled, TX high, other outputs off)
    TRISB = 0b10010011;         // Set PORTB pin directions: RB2, RB3, RB5, RB6 output, all others input
 
    PORTC = 0b00000000;         // Initial state of PORTC (turn LEDs, outputs off)
    TRISC = 0b11100000;         // Set PORTC pin directions: RC0-RC4 output, RC5-RC7 input
}




ports.h

Code C - [expand]
1
void initPorts(void);




usart.c

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Main.h"
//=============================================================================
// Filename: usart.c
//=============================================================================
 
void initComms()
{
    /* Serial port initialization */
    /*
    TXSTA2bits.BRGH = 1;
    TXSTA2bits.SYNC = 0;
    SPBRGH2 = 0;
    SPBRG2 = 25;                    //((FCY/16)/BAUD) - 1; // set baud to 9600  FCY=4000000
    BAUDCON2 = 0x08;                //BRGH16 = 1
 
    TXSTA2bits.TXEN = 1;            //Enables transmitter
    RCSTA2bits.CREN = 1;            //Enables receiver
    RCSTA2bits.SPEN = 1;            //Enable UART
    */
 
 
    TXSTA2bits.CSRC = 0;
    TXSTA2bits.TX9 = 0;
    TXSTA2bits.TXEN = 1;
    TXSTA2bits.SYNC = 0;
    TXSTA2bits.SENDB = 0;
    TXSTA2bits.BRGH = 1;
    TXSTA2bits.TRMT = 1;
    TXSTA2bits.TX9D = 0;
 
    RCSTA2bits.SPEN = 1;
    RCSTA2bits.RX9 = 0;
    RCSTA2bits.SREN = 0;
    RCSTA2bits.CREN  = 0;
    RCSTA2bits.ADDEN = 0;
    RCSTA2bits.FERR = 0;
    RCSTA2bits.OERR = 0;
    RCSTA2bits.RX9D = 0;
 
    BAUDCON2bits.ABDOVF = 0;
    BAUDCON2bits.RCIDL = 1;
    BAUDCON2bits.RXDTP = 0;
    BAUDCON2bits.TXCKP = 0;
    BAUDCON2bits.BRG16 = 1;
    BAUDCON2bits.WUE = 0;
    BAUDCON2bits.ABDEN = 0;
 
    SPBRGH2 = 0;
    //SPBRG = 1.3;
 
    SPBRG2 = 25;                    //((FCY/16)/BAUD) - 1; // set baud to 9600  FCY=4000000
 
 
 
}
 
void writeStringToUART (const char *msg)
{
    while(*msg)    {
        while(PIR3bits.TX2IF == 0) {}
        TXREG2 = *msg++;
    }
}
 
/*void writeStringToUART (const char* msg)
{
//    char index = 0;
    while (msg[0] != 0) {
//        while (!TRMT2);
        while (PIR3bits.TX2IF == 0) {}
        TXREG2 = msg[0];
//        Nop();
        msg++;
    }
}*/




usart.h

Code C - [expand]
1
2
3
4
5
6
7
#ifndef _SERIAL_H_
#define _SERIAL_H_
 
void initComms();
void writeStringToUART (const char* msg);
 
#endif



- - - Updated - - -

Post code related to Oscillator settings. Are you using INTRC OSC or EXT XT OSC? What is Fosc? The SPBRGx values I gave is for 4 MHz Fosc.

See the code in the last post. I'm using the internal HS RC oscillator.

Page 333 of datasheet tells this.

For EUSART2:
- SPEN (RCSTA2<7>) must be set (= 1)
- TRISx<x> must be set (= 1)
- For Asynchronous and Synchronous Master
modes, TRISx<x> must be cleared (= 0)

Yeah, I saw this, but I wasn't quite sure which bit they were referring to when they wrote TRISx<x>. I interpreted it as TRISB<7> must be set, and for async, TRISB<6> must be cleared, which is what I have.
 


Code C - [expand]
1
spbrg2 = 103;


You're right, I was using the formula for BRGH = 0, getting SPBRG2 = 25. Strangely, I'm getting 9600 baud. I have another similar strange problem with Fosc being 4MHz even with OSCCON set for 1Mhz.

I wonder if these timing issues are causing the string problems. I just don't see where the problem is.

Actually, maybe I am actually getting 1MHz. I thought I was getting four times the frequency based on the Delay_ms function but maybe those calculations are all off. So if I am at 1MHz, then SPBRG=25 is correct for 9600 baud.

- - - Updated - - -

Well, I changed OSCCON to 0x50 and SPBRG2 to 103 and I still get 9600 baud, but no change to the UART output. The first and only thing that prints is "This works" repeatedly. The Delay_ms is too fast now, but I'll adjust that later, or maybe use a timer interrupt.
 

I solved the problem. All it took was adding "#include "xc.h"" line above the pragmas and moving "#include "main.h"" below them, in main.c Everything works perfectly after doing this.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top