Chami Perera
Chami Perera

Reputation: 19

Transmitting 10bit data through The UART of PIC16F877A

I'm beginner to micro controller technology. I want to transmit the 10-bit output I got from an Analog to Digital Conversion, but only 8 bits can be sent via the UART. How can I send 10 bits?

Please help me to write C code to solve this problem. My code so far is given below. The compiler used is XC8.

#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000

#include <stdio.h>
#include <stdlib.h>

#include <htc.h>

void uart_init(void);
void TX(unsigned char TX_BYTE);
void configure_pins();
unsigned char read_input(unsigned char channel);

void main()
{
    __delay_ms(2);
    while (1) {
        TRISB = 0;  //configuring portB as output
        TRISC = 0;
        TRISA = 1;

        configure_pins();                   //calling methods
        unsigned char x = read_input(0);
        uart_initialize();
        assign_data_to_tx_pin(x);
    }
}

void configure_pins(){
    ADCON1 = 0b10000000;             //The result is right justified
}

unsigned char read_input(unsigned char channel){  // converting the Analog input to digital
    ADCON0=0b00000000;
    CHS0=0;                  // AN0 is selected
    CHS1=0;                  // "
    CHS2=0;                  // "

    ADON = 1;
    GO_DONE = 1;

    while (GO_DONE);
    ADON = 0;
    return ((ADRESH >> 2) + ADRESL);      // return the result of conversion
}

void uart_initialize(void)            // initializing the UART for data transmission
{

    TRISC = 0;           //configuring portC as output

    TXSTA = 0b100000000;
    TXEN = 1;            //enable transmission mode
    SPEN = 1;            //enable UART
    BRGH = 0;            //enable low baud
    SPBRG = 6;           //set baud rate as 9600
    SYNC = 0;            //enable asynchronous transmission

    RCIE = 1;
    GIE = 1;
    PEIE = 1;
}

void assign_data_to_tx_pin(unsigned char converted_data) {  // assigning the data to the Tx pin for transmission
    while(!TRMT) {
        unsigned char a = converted_data;

        TXREG = a; 
        TXREG = a >> 2; 
        PORTCbits.RC6 = TXREG;

        __delay_ms(100); // Delay
    }
}

Upvotes: 1

Views: 1995

Answers (2)

chux
chux

Reputation: 154208

Typical UARTs do not allow for more than 8 bits of data per transmission. Some allow 9. Sending 10 bits may be available on select UARTS using 9 bits and controlling the parity, but that is rare.

Instead recommend to send the data as 2 transmission with a bit set aside to denote which half is sent.

Send_ADC(void){
  ADCON0=0b00000000;
  CHS0=0;                  // AN0 is selected
  CHS1=0;                  // "
  CHS2=0;                  // "
  ADON = 1;
  GO_DONE = 1;
  while (GO_DONE);
  ADON = 0;
  unsigned adc10 = ((ADRESH >> 2) + ADRESL); 
  assign_data_to_tx_pin((adc10 % 32) * 2 + 0);   // 00lllll0
  assign_data_to_tx_pin((adc10 / 32) * 2 + 1);   // 00hhhhh1
}

On receiver side, insure bytes received are in the proper byte order. This will re-construct the received data in the proper order, even if reception does not start in phase or if a byte was lost in communication.

// return 0: success, else 1
int ReadSerialADC(unsigned *data) {
  unsigned adc;
  unsigned low = read_from_comport();
  if (low %2) return 1;
  low /= 2;
  unsigned high = read_from_comport();
  if (high %2 == 0) return 1;
  high /= 2;
  *data = high * 32 + low;
  return 0;
}

Upvotes: 1

Weather Vane
Weather Vane

Reputation: 34583

You are reading a 10-bit ADC result with like this

return ((ADRESH>>2)+ADRESL);

But the function is return unsigned char, it should be unsigned int

unsigned int read_input(unsigned char channel)

and the calling function is also throwing away two bits with

unsigned char x=read_input(0);

which should be

unsigned int x=read_input(0);

Having read a 10-bit value into a (presumably) 16-bit variable, you now have to transmit it to the serial port. Let's do this by sending the most significant 8 bits first.

TX (x >> 8);
TX (x & 0xFF);

Then at the receiver end you read the two bytes and put them back together

unsigned adcval = RX() << 8;
adcval |= RX();

Upvotes: 0

Related Questions