UART

UART interface module facilitates transmission or reception of data with the external world. We can use this interface to communicate with computer or other device which supports same type of interface. Though UART module has its own data transaction pattern one exception it still there. It can be used to shift data bits as it is a kind of serial interface.


[SCON register]
SCON register is used to perform all control operation for the Serial module. It also reflects various interrupt status of data transactions as well as error identification.


[PCON register] 
PCON register has one bit called SMOD which is used to double the currently selected serial baud rate.


Now we will discuss about the serial module driver and how can we use it at different crystal and baud settings.

[serial.h]
This is the serial driver header file. User has to declare the crystal associated with controller by using XTAL_FREQ.

#ifndef __SERIAL_2_H__
#define __SERIAL_2_H__

#define XTAL_FREQ 12000000

#if XTAL_FREQ==11059200
static unsigned int timer1_reload_settings[3] = { 0x00E8, 0x00FD, 0x01FD };
static unsigned int timer2_reload_settings[3] = { 0xFEE0, 0xFFDC, 0xFFEE};
#endif

#if XTAL_FREQ==12000000
static unsigned int timer1_reload_settings[3] = { 0x00E6, 0x0000, 0x0000 };
static unsigned int timer2_reload_settings[3] = { 0xFEC8, 0xFFD9, 0x0000};
#endif

#if XTAL_FREQ==16000000
static unsigned int timer1_reload_settings[3] = { 0x00DE, 0x00F5, 0x0000 };
static unsigned int timer2_reload_settings[3] = { 0xFE5F, 0xFFCC, 0xFFE6 };
#endif

#include <ioat89c55wd.h>

#define TranmitData(tdata) SBUF = tdata

typedef enum {
  serial_clksrc_timer1 = 0,
  serial_clksrc_timer2 = 1,
  serial_clksrc_internal = 2
} serial_clksrc;

typedef enum {
  serial_baud_1200 = 0,
  serial_baud_9600 = 1,
  serial_baud_19200 = 2,
} serial_baudrate;

typedef enum {
  serial_mode_8bit_shift = 0,
  serial_mode_8bit_variable = 1,
  serial_mode_9bit_fixed = 2,
  serial_mode_9bit_variable = 3
} serial_mode;

struct t_serial_callbacks {
  void (*pfnTransmit) (unsigned char);
  void (*pfnReceive) (unsigned char);
};

void SerialInit(serial_clksrc,serial_baudrate,serial_mode);
void Serial_RegCallbacks(struct t_serial_callbacks *);
void Serial_UnregCallbacks();

#endif

[serial.c]
This is the driver file for serial module.

#include "serial.h"
#include "timer_0_1.h"
#include "timer2.h"

static struct t_serial_callbacks *p_serial_callbacks;

#pragma vector=0x23
__interrupt void serial_interrupt_handler(void) {
  if(SCON_bit.TI == 1) {
    p_serial_callbacks->pfnTransmit(0x00);
  }
  if(SCON_bit.RI == 1) {
    p_serial_callbacks->pfnReceive(SBUF);
  }
}

void SerialInit(serial_clksrc clksrc,serial_baudrate baudrate,serial_mode mode) {
  switch(clksrc) {
  case serial_clksrc_timer1:
    T2CON_bit.TCLK = 0;
    T2CON_bit.RCLK = 0;
    Timer01_Init(timer01_id_1,timer01_mode_reload,timer01_clk_internal);
    TIMER01_REG_HIGH(timer01_id_1) = (unsigned char) timer1_reload_settings[baudrate];
    PCON_bit.SMOD = (timer1_reload_settings[baudrate] & 0x0100) ? 1 : 0;
    Timer01_Run(timer01_id_1);
    break;
  case serial_clksrc_timer2:
    T2CON_bit.TCLK = 1;
    T2CON_bit.RCLK = 1;
    Timer2_SetRelod(timer2_reload_settings[baudrate]);
    Timer2_Run();
    break;
  }
  SCON = mode << 0x06;
}

void Serial_RegCallbacks(struct t_serial_callbacks *serial_callbacks) {
  IE_bit.ES = 1;
  p_serial_callbacks = serial_callbacks;
}

void Serial_UnregCallbacks() {
  IE_bit.ES = 0;
}

[main.c]
In this file I will show the code needed to use the driver file.

#include <serial.h>
#include <ioat89c55wd.h>

unsigned char wait = 0;

void SerialTransmit(unsigned char);
void SerialReceive(unsigned char);

static struct t_serial_callbacks serial_callbacks = {
                                                        .pfnTransmit = SerialTransmit,
                                                        .pfnReceive = SerialReceive
                                                      };

int main( void )
{

  SerialInit(serial_clksrc_timer2,serial_baud_1200,serial_mode_8bit_variable);
  Serial_RegCallbacks(&serial_callbacks);
 
  IE_bit.EA = 1; // Enable global 

  while(1) {

    if(!wait) {
        TranmitData((unsigned char) i);
        wait = 1;
        i++;
       while(i > 80) i =65;
    }

  //return 0;
 }


void SerialTransmit(unsigned char tdata) {
  toggle = 0;
  P0 = P0 ^ 0x08; // Transmission status output
}

void SerialReceive(unsigned char rdata) {
  // User can write code here to save incoming data to a buffer
}

N.B: Thanks for reading my article. I will update this article latter. Requesting for your suggestions. Timer2 and Serial port is coming soon.

No comments:

Post a Comment