简体   繁体   中英

PIC16F887 UART read a string and then cut that string into 3 arrays

Hi Everyone I am working on finishing a project and have hit a dead end. I am new to C and I am trying to write a program that can read in a string from the RX pin on a PIC16F887. The RX pin is connected to an XBee which receives data from a PC via another XBee and a serial terminal on digis XCTU. I want to be able to send a 16 bit string of binary from the PC then receive it on the PIC16F887 cut it into 3 parts. 1st part is the 1st digit then 2nd part is the next 7 digits and then the last part (part 3) is the next 8 digits.

I have been using this example as a guide (google) ( https://electrosome.com/uart-pic-microcontroller-mplab-xc8/ ) But I am not that great with C at all really. ` /* * File: SerialComsMain.c * Author: Jonathan * PIC16F887 with an XBee Connected to RC6 (PIC TX) connected to XBee RX * RC7(PIC RX) connected to XBee TX. * L298N motor Driver is used to drive two 6 volt motors * Port D is used to control the L298N * RDO is In1, RD1 is In2, RD2 is In2 and RD3 is In3 * RC1 is a PWM signal used to drive motor A via En A * RC2 is a PWM signal used to drive motor B via En B * Created on 02 March 2015, 15:27 */

#include <xc.h>                 // Using the xc 8 compiler
#include <pic16f887.h>          // Must include as using a PIC16F887
#include <stdio.h>
#define _XTAL_FREQ 8000000     // 10MHz clock (not used for internal clock

#pragma config "FOSC = INTRC_NOCLKOUT"      // Using INTOSC internal 8MHz
#pragma config "WDTE = OFF"     // Watchdog Timer Enable bit
#pragma config "PWRTE = OFF"    // Power-up Timer Enable bit
#pragma config "CP = OFF"       // Code Protection bit
#pragma config "BOREN = ON"     // Brown Out Reset Selection bits

char command[41];
char text[41];
char Output[41];
char length [41];
void UART_Write_Text(char *);   //
void UART_Read_Text(char *, unsigned int);
char UART_Read();
char UART_Data_Ready();

void main(void)
{
    int i;
        // init port
    PORTD = 0;
    TRISD = 0b00000000;     // all outputs (
    PORTC = 0;              // port c set to 0
    TRISC = 0b10000000;     // all outputs, except RX on RC7
    BRGH = 1;               // use high range internal osc
    SPBRG = 25;             // 9600 baud with 8MHz clock.
    SYNC = 0;               //Setting Asynchronous Mode, ie UART
    SPEN = 1;               //Enables Serial Port
    TRISC7 = 1;             //As Prescribed in Datasheet
    TRISC6 = 1;             //As Prescribed in Datasheet
    CREN = 1;               //Enables Continuous Reception
    TXEN = 1;               //Enables Transmission
    PORTD = 0b00000001;
    __delay_ms(500);

    for (i = 0; i < 10; i++)
    {
        sprintf(command,"hello %i\r\n",i+1);
        UART_Write_Text(command);
        __delay_ms(500);
    }

}

void UART_Write_Text(char *command)
{
  int i;
  for(i=0;command[i]!='\0';i++)
  {
      while(!TRMT);
      TXREG = command[i];
  }
}

void UART_Read_Text(char *Output, unsigned int length)
{
  unsigned int i;
  for(int i=0;i<length;i++)
  Output[i] = UART_Read();
}

char UART_Read()
{
  while(!RCIF);
  return RCREG;
}

char UART_Data_Ready()
{
  return RCIF;
}

`

At the moment this code above send hello world with a number 1,2,3 up to 20 and repeats. this was just to test I could send data but now as mentioned above I want to change the code to receive a string of binary and chop it into three pieces.

I am using MPlab X IDE and a PICKIT 3 to program the PIC Thanks

First, I strongly suggest that you buy a decent book on C and/or go through at least one tutorial on C programming. I would bet that if you do this you would be able to answer this question yourself.

Also, the issue of chopping 16 bits into three pieces has nothing to do with the UART, so you should consider removing those details from your question. The source of the bits does not matter; you can manipulate bits from any source.

My understanding of your problem is that you have a 16-bit value that is read in from the UART, and you want to split that into three values in the following manner:

| 15 | 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0 |

Being able to pick out specific bits of data is essential in embedded programming. This is usually done through bit shifting and masking operations. The idea is to first mask the bits that you want to keep, and then you shift out the unwanted bits. In your case something like this would work:

#include <stdio.h>

int main(void)
{
    unsigned short value = 0x9234;
    unsigned char one, two, three;

    one   = (0x8000 & value) >> 15;    // mask the first bit and shift 
    two   = (0x7F00 & value) >> 8;     // mask the next 7 bits and shift
    three = (0x00FF & value);          // mask final 8 bits, no need to shift

    printf("one: %02X\ntwo: %02X\nthree: %02X\n", one, two, three);

    return 0;
}

The output of the above code is:

myFavoriteUser:~$ make test
cc     test.c   -o test
myFavoriteUser:~$ ./test
one: 01
two: 12
three: 34

To get the first bit we are masking with the 16-bit value by bitwise ANDing our number with 0x8000 = 0b1000000000000000 and then shifting the result 15 bits to the right to get our desired bit value. For the second chunk we mask with 0x7F00 = 0b0111111100000000 to get the next 7 bits, which we then shift to the right by 8 bits so they represent the correct value. We then mask the lowest 8 bits, which are already lined up and don't require shifting.

Now where your UART does come into play is in how you are transmitting and receiving your 16 bits of data. I would be careful using your existing UART_Read_Text() function; it does not guarantee that an incoming string will be null-terminated.

Use a union to access at byte level and bit level at the same time:

typedef union
{
  struct
  {
     unsigned int bits0: 1;  //bit0
     unsigned int bits1: 7;  //bits1:7
     unsigned int bits2: 8;  //bits8:15
  }
  char b[2];  //bits0:15
} my_union_t;

Then you can assign the union from reading:

my_union_t val;
val.b[0] = UART_Read();
val.b[1] = UART_Read();

Then you can access the individual bitfields:

if (val.bits0)
{
  //something
}
if (val.bits1 == 2)
{
  //something
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM