UART: Only receiving mess on RasberryPi when connected to a PIC18

I have a PIC18LF27J53 running properly and I'm able to make an LED blink. FOSC is at 8MHz (which is confirmed through the LED).

Now, I want to make the PIC send some bytes to the RaspberryPi via UART (I'm using minicom to inspect /dev/ttyAMA0 and have disabled both bluetooth and the serial console). I tried with both TX1 and remapped TX2 but I'm only receiving the same mess (fààþæ). I tried to invert the logic, but that didn't help and I'm receiving ~øxøxxøxþ instead.

This is my code to setup the UART interface (with BRGH, 8-bit BRG @ 9600):

TXSTA2   = 0b10100110;
RCSTA2   = 0b00010000;
BAUDCON2 = 0b01000010;
// BR=FOSC/(16(n+1)) <=> n=FOSC/BR/16-1
n = (uint8_t)round(1.0 * CLOCKSPEED / BAUDRATE / 16.0) - 1;
SPBRG2 = n;
RCSTA2bits.SPEN = 1;


The formula outputs 51 for CLOCKSPEED = 8MHz and BAUDRATE = 9600 which is the same as written in the datasheet (page 343).

This is the code I use to send a string:

void putc(char c)
{
while(TXSTA2bits.TRMT == 0);
TXREG2 = c;
}
void puts(const char *str)
{
const char *p;
for (p = str; *p; p++)
putc(*p);
}


Finally, I call it like this:

const char *str = "HELLO\r\n";
puts(str);


What can I do to make the RaspberryPi receive the correct characters?

EDIT: I just tried to print the character U (01010101) continously via UART. Minicom receives continously alternating the chars f (01100110) and æ (11100110). So I'd guess that there is an issue with the baud rate. How can I check this and find the error?

• Default INTOSC frequency is 4 MHz. Show us your CONFIG register settings and system clock initialization code. – Bruce Abbott Jan 23 '17 at 18:23
• @BruceAbbott INTOSC is a 8MHz clock but it seems the derived FOSC is only 4MHz by default. I was using the default config of XC8, but setting PLLDIV to 2 and the IRCF bits to 7 it's now working without ugly workaround. – msrd0 Jan 23 '17 at 18:41
• @BruceAbbott do you know whether the PLL will influence the value I have to use for CLOCKSPEED or will it always be calculated from INTOSC clock? – msrd0 Jan 23 '17 at 18:41
• Examine the clock circuit on page 32 of the datasheet:- "FIGURE 3-1: PIC18F47J53 FAMILY CLOCK DIAGRAM". There are several different ways to set the system clock frequency. With OSCCON<1:0> = 00 (default value) the system clock comes from INTOSC postscaled by OSCCON<6:4>, and the PLL has no effect. – Bruce Abbott Jan 23 '17 at 19:02

I connected the TX pin of the PIC to a GPIO input pin of my RaspberryPi and wrote a little program to monitor what's going on:

    #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

#define BLOCK_SIZE 256

#define GPIO_IN(g)  *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define GPIO_OUT(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))

#define GPIO_SET(g)  *(gpio+7)  = 1<<(g)
#define GPIO_CLR(g)  *(gpio+10) = 1<<(g)
#define GPIO_LEV(g) (*(gpio+13) >> (g)) & 0x1

#define PIN 18

int                mem_fd;
void              *gpio_map;
volatile uint32_t *gpio;

unsigned long ellapsed(struct timespec last, struct timespec now)
{
unsigned long diff = now.tv_sec - last.tv_sec;
diff *= 1e9;
diff += now.tv_nsec - last.tv_nsec;
return diff;
}

int main()
{
mem_fd = open("/dev/gpiomem", O_RDWR|O_SYNC);
assert(mem_fd != -1);

gpio_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0);
assert(gpio_map != MAP_FAILED);
gpio = (volatile uint32_t*)gpio_map;

GPIO_IN(PIN);

struct timespec last, now;
clock_gettime(CLOCK_BOOTTIME, &last);
char state = 1;
while (1)
{
if ((state & 0x1) != (GPIO_LEV(PIN)))
{
clock_gettime(CLOCK_BOOTTIME, &now);
printf("state changed from %d to %d after %f µsecs (= %f kHz)\n", state, GPIO_LEV(PIN), ellapsed(last, now)/1000.0, 1.0/(ellapsed(last,now)/1e9)/1e3);
last = now;
state = GPIO_LEV(PIN);
}
}
}


The speed was about 207 µsec per bit. I looked up the speed of uart and found that this equals a baud rate of 4800, exactly half of what I expected. Dividing n through 2 gives me the correct baud rate, although I don't understand why this is needed, as neither the datasheet nor the internet tells about such behaviour.

• This isn't really an answer, it's just conforming that the baud rate is half what you expected. – Bruce Abbott Jan 23 '17 at 17:35
• @BruceAbbott It is an ugly workaround but fixed my problem so I'd call it an answer. Still I don't know what causes the issue so if you know it please provide a better answer – msrd0 Jan 23 '17 at 17:48