简体   繁体   English

PIC16F887 UART读取一个字符串,然后将该字符串切成3个数组

[英]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. 我是C语言的新手,我正在尝试编写一个可以从PIC16F887的RX引脚读取字符串的程序。 The RX pin is connected to an XBee which receives data from a PC via another XBee and a serial terminal on digis XCTU. RX引脚连接到XBee,后者通过另一个XBee和digis XCTU上的串行端子从PC接收数据。 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. 我希望能够从PC发送一个16位二进制字符串,然后在PIC16F887上接收它,并将其分为3部分。 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. 第一部分是第一位数字,第二部分是接下来的7位数字,然后最后一部分(部分3)是接下来的8位数字。

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. 我一直在用这个例子作为指南(谷歌)( https://electrosome.com/uart-pic-microcontroller-mplab-xc8/ ),但是我对C的理解并不是很好。 ` /* * 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. `/ * *文件:SerialComsMain.c *作者:Jonathan * PIC16F887,其XBee已连接到RC6(PIC TX),该X6e已连接到XBee RX * RC7(PIC RX)已连接到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 */ * L298N电动机驱动器用于驱动两个6伏电动机*端口D用于控制L298N * RDO是In1,RD1是In2,RD2是In2和RD3是In3 * RC1是用于通过En驱动电动机A的PWM信号A * RC2是用于通过En B驱动电机B的PWM信号*创建于2015年3月2日,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. 目前,上面的代码向您好世界发送数字1,2,3(最多20)并重复。 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 我正在使用MPlab X IDE和PICKIT 3对PIC编程,谢谢

First, I strongly suggest that you buy a decent book on C and/or go through at least one tutorial on C programming. 首先,我强烈建议您购买一本不错的C语言书籍,并且/或者至少阅读一本有关C编程的教程。 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. 另外,将16位分成三部分的问题与UART无关,因此您应该考虑从问题中删除那些细节。 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: 我对您的问题的理解是,您有一个从UART读取的16位值,并且您希望通过以下方式将其分为三个值:

| | 15 | 15 | 14 13 12 11 10 9 8 | 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0 | 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. 为了获得第一位,我们通过对数字与0x8000 = 0b1000000000000000进行按位与运算,然后将结果向右移15位,以获得期望的位值,从而使用16位值进行掩蔽。 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. 对于第二个块,我们使用0x7F00 = 0b0111111100000000进行掩码以获得下一个7位,然后将其向右移8位,以便它们表示正确的值。 We then mask the lowest 8 bits, which are already lined up and don't require shifting. 然后,我们屏蔽最低的8位,这些位已经排列好了,不需要移位。

Now where your UART does come into play is in how you are transmitting and receiving your 16 bits of data. 现在,您的UART发挥作用的地方是如何发送和接收16位数据。 I would be careful using your existing UART_Read_Text() function; 我会谨慎使用您现有的UART_Read_Text()函数; 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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