Friday, December 30, 2011

PIC16F877 Timer Modules tutorials


Discription :
Many times, we plan and build systems that perform various processes that depend on time.
Simple example of this process is the digital wristwatch. The role of this electronic system is to display time in a very precise manner and change the display every second (for seconds), every minute (for minutes) and so on.
To perform the steps we've listed, the system must use a timer, which needs to be very accurate in order to take necessary actions.The clock is actually a core of any electronic system
n this PIC timer module tutorial we will study the existing PIC timer modules. The microcontroller PIC16F877 has 3 different timers 
  • Timer 0
  • Timer1
  • Timer2
We can use these timers for various important purposes. So far we used “delay procedure” to implement some delay in the program, that was counting up to a specific value, before the program could be continued. "Delay procedure" had two disadvantages:
  • we could not say exactly how long the Delay procedure was in progress
  • we could not perform any further steps while the program executes the "delay procedure"
Now, using Timers we can build a very precise time delays which will be based on the system clock and allow us to achieve our desired time delay well-known in advance.
In order for us to know how to work with these timers, we need to learn some things about each one of them. We will study each one separately.

PIC Timer0 tutorial

The Timer0 module timer/counter has the following features:
  • 8-bit timer/counter
  • Readable and writable
  • 8-bit software programmable prescaler
  • Internal (4 Mhz) or external clock select
  • Interrupt on overflow from FFh to 00h
  • Edge select (rising or falling) for external clock
Let’s explain the features of PIC Timer0 we have listed above:

Timer0 has a register called TMR0 Register, which is 8 bits of size.
We can write the desired value into the register which will be increment as the program progresses. Frequency varies depending on the Prescaler. Maximum value that can be assigned to this register is 255. 
TMR0IF - TMR0 Overflow Interrupt Flag bit.
The TMR0 interrupt is generated when the TMR0 register overflows from FFh to 00h. This overflow sets bit TMR0IF (INTCON<2>). You can initialize the value of this register to what ever you want (not necessarily "0").
We can read the value of the register TMR0 and write into. We can reset its value at any given moment (write) or we can check if there is a certain numeric value that we need (read).
Prescaler - Frequency divider.
We can use Prescaler for further division of the system clock. The options are:
  • 1:2
  • 1:4
  • 1:8
  • 1:16
  • 1:32
  • 1:64
  • 1:128
  • 1:256

The structure of the OPTION_REG register

We perform all the necessary settings with OPTION_REG Register. The size of the register is 8 bits
OPTION REGISTER

Initializing the OPTION_REG register

The following is an example how we can initialize the OPTION_REG:
  1. PSA=0; // Prescaler is assigned to the Timer0 module
  2. PS0=1; // Prescaler rate bits
  3. PS1=1; // are set to “111”
  4. PS2=1; // which means divide by 256
  5. TOSE=0; // rising edge
  6. TOCS=0; // Internal instruction cycle clock

Block diagram of the PIC Timer0 / WDT prescaler

TIMER0 BLOCK DIAGRAM
PIC TIMER0 block diagram

Calculating Count, Fout, and TMR0 values

If using INTERNAL crystal as clock, the division is performed as follow:
TIMER0 formula
PIC TIMER0 formula for internal clock
Fout– The output frequency after the division.
Tout – The Cycle Time after the division.
4 - The division of the original clock (4 MHz) by 4, when using internal crystal as clock (and not external oscillator).
Count - A numeric value to be placed to obtain the desired output frequency - Fout.
(256 - TMR0) - The number of times in the timer will count based on the register TMR0.

An example of INTERNAL crystal as clock

Suppose we want to create a delay of 0.5 second in the our program using Timer0. What is the value of Count?
Calculation:
First, let’s assume that the frequency division by the Prescaler will be 1:256. Second, let’s set TMR0=0. Thus:
TIMER0 formula
Formula to calculate Cout using Timer0
If using EXTERNAL clock source (oscillator), the division is performed as follow:
TIMER0 formula
PIC TIMER0 formula for external clock
In this case there is no division by 4 of the original clock. We use the external frequency as it is.

An example of EXTERNAL clock source (oscillator):

What is the output frequency - Fout, when the external oscillator is 100kHz and Count=8?
Calculation:
First, let’s assume that the frequency division by the Prescaler will be 1:256. Second, let’s set TMR0=0. Thus:
TIMER0 formula
Formula to calculate Fout for Timer0

Delay of 1 sec using Timer0

The following simple program creates a delay of 1 sec using Timer0:
1 sec delay using TIMER0
1 sec delay using Timer0




PIC Timer1 tutorial

The Timer1 module, timer/counter, has the following features:
  • 16-bit timer/counter consisting of two 8-bit registers (TMR1H and TMR1L)
  • readable and writable
  • 8-bit software programmable prescaler
  • Internal (4 Mhz) or external clock select
  • Interrupt on overflow from FFFFh to 0000h
et’s explain the features of PIC Timer1 we have listed above:
Timer1 has a register called TMR1 register, which is 16 bits of size. 
Actually, the TMR1 consists of two 8-bits registers: 
  • TMR1H
  • TMR1L
It increments from 0000h to the maximum value of 0xFFFFh (or 0 b1111 1111 1111 1111 or 65,535 decimal). The TMR1 interrupt, if enabled, is generated on overflow which is latched in interrupt flag bit, TMR1IF (PIR1<0>). This interrupt can be enabled/disabled by setting/clearing TMR1 interrupt enable bit, TMR1IE (PIE1<0>). You can initialize the value of this register to what ever you want (not necessarily "0").
TMR1IF – TMR1 overflow Interrupt Flag bit.
This flag marks the end of ONE cycle count. The flag need to be reset in the software if you want to do another cycle count. We can read the value of the register TMR1 and write into. We can reset its value at any given moment (write) or we can check if there is a certain numeric value that we need (read).
Prescaler – Frequency divider. 
We can use Prescaler for further division of the system clock. The size of the register is 2-bit only, so you can make four different division. The options are:

  • 1:1
  • 1:2
  • 1:4
  • 1:8
You can choose whether to use an internal system clock (crystal) or external oscillator that can be connected to a pin RC0.

The structure of the T1CON register

We perform all the necessary settings with T1CON register. As we can see, the size of the register is 8 bits. Let’s explore the relevant bits:
T1CON register

Initializing the T1CON register

The following is an example how we can initialize the T1CON register:
  1. TMR1ON=1; // the timer is enable
  2. TMR1CS=0; // internal clock source
  3. T1CKPS0=0; // Prescaler value set to “00”
  4. T1CKPS1=0; // which means 1:1 (no division)
Or you can set all the T1CON register at once as follows:
T1CON=0b00000001;
CLICK here for more information about PIC TIMER 1 Module

Block diagram of the PIC Timer1

TIMER1 BLOCK DIAGRAM
PIC TIMER1 block diagram

Calculating Count, Fout, and Timer1 values

If using INTERNAL crystal as clock, the division is performed as follow:
TIMER1 formula
PIC TIMER1 formula for internal clock
Fout– The output frequency after the division.
Tout – The Cycle Time after the division.
4 - The division of the original clock (4 MHz) by 4, when using internal crystal as clock (and not external oscillator).
Count - A numeric value to be placed to obtain the desired output frequency - Fout.
(256 - TMR1) - The number of times in the timer will count based on the register TMR0.
If using EXTERNAL clock source (oscillator), the division is performed as follow:
TIMER1 formula
PIC TIMER1 formula for external clock

Simple example and calculation of how to use TIMER1:

Suppose we want to create a delay of 2 second in the our program using Timer1. What is the value of Count?
Calculation:
First, let’s assume that the frequency division by the Prescaler will be 1:1. Second, let’s set TMR1=0, which means the TMR1 will count 65,536 times. Thus:
TIMER1 COUNT CALCULATION
Formula to calculate Cout for Timer1

Delay of 1 sec using Timer1

The following simple program creates a delay of 1 sec using TIMER1:
#include<pic.h>

int Count = 0;
void main (void)
{
T1CON = 0b00000001;
while (1)
{
while (! TMR1IF);
TMR1IF = 0;
Count ++;
if (Count == 15)
{
Count = 0;
}
}

1 sec delay using Timer1


Timer2
The Timer2 module has the following features:
• two 8-bit registers (TMR2 and PR2)
• readable and writable
• prescaler and a postscaler
• connected only to an internal clock - 4 MHz crystal
• Interrupt on overflow
Let’s explain the features we have listed above:
• Timer2 has 2 count registers: TMR2 and PR2. The size of each registers is 8-bit in which we can write numbers from 0 to 255. The TMR2 register is readable and writable and is cleared on any device Reset. PR2 is a readable and writable register and initialized to FFh upon Reset.
Register TMR2 is used to store the “initial” count value (the value from which it begins to count). Register PR2 is used to store the “ending” count value (the maximum value we need/want to reach). ie: using Timer2 we can determine the started count value, the final count value, and the count will be between these two values. The Timer2 increments from 00h until it matches PR2 and then resets to 00h on the next increment cycle.
• Prescaler and Postscaler - Timer2 is an 8-bit timer with a prescaler and a postscaler. Each allows to make additional division of the frequency clock source.
Prescaler divides the frequency clock source BEFORE the counting take place at the register TMR2, thus the counting inside the TMR2 register is performed based on the divided frequency clock source by the Prescaler
The match output of TMR2 goes through a 4-bit postscaler (which gives a 1:1 to 1:16 scaling inclusive) to generate a TMR2 interrupt (latched in flag bit, TMR2IF (PIR1<1>)).
Postscaler divides the frequency that comes out of the Comparator again for the last time.
TIMER2 Prescaler and Postscaler
TIMER2 prescaler postscaler

• TMR2IF - TMR2 to PR2 Match Interrupt Flag bit.
• Comparator – Compares the value of the register TMR2 and the maximum value of the register PR2.
• TMR2 – The register in which the “initial” count value is written.
• PR2 – The register in which the final or the maximum count value is written. 
We perform all the necessary settings with T2CON Register The structure of the T2CON register:
T2CON register 
As we can see, the size of the register is 8 bits. Let’s explore the relevant bits:
T2CKPS1:T2CKPS0: Timer2 Clock Prescale Select bits
The input clock (FOSC/4) has a prescale option of 1:1, 1:4 or 1:16, selected by control bits T2CKPS1:T2CKPS0 (T2CON<1:0>).
00 = Prescaler is 1
01 = Prescaler is 4
1x = Prescaler is 16
TMR2ON: Timer2 On bit
Timer2 can be shut-off by clearing control bit, TMR2ON (T2CON<2>), to minimize power consumption.
1 = Timer2 is on
0 = Timer2 is off
TOUTPS3:TOUTPS0: Timer2 Output Postscale Select bits
The match output of TMR2 goes through a 4-bit postscaler (which gives a 1:1 to 1:16 scaling inclusive selected by control bits TOUTPS3:TOUTPS0 (T2CON<6:3>).
0000 = 1:1 postscale
0001 = 1:2 postscale
0010 = 1:3 postscale



1111 = 1:16 postscale
The following is an example how we can initialize the T2CON register:
1. TMR2ON=1; // the timer is enable
2. T2CKPS0=0; // Prescaler – 1:1
3. T2CKPS1=0; 
4. TOUTPS0=1; // Postscaler – 1:16
5. TOUTPS0=1;
6. TOUTPS0=1;
7. TOUTPS0=1;
Or you can set all the T2CON register at once as follows:
T2CON=0b01111100;
TIMER2 BLOCK DIAGRAM
TIMER2 BLOCK DIAGRAM

How to calculate the required values of the TIMER2:
TIMER2 FORMULA
Fout – The output frequency after the division.
Tout – The Cycle Time after the division.
4 - The division of the original clock (4 MHz) by 4, when using internal crystal as clock (and not external oscillator).
Count - A numeric value to be placed to obtain the desired output frequency - fout.
(PR2 – TMR2) - The number of times the counter will count.
Simple example and calculation of how to use TIMER2:
Suppose we want to create a delay of 1 second in the our program using Timer2. What is the value of Count?
Calculation:
First, let’s assume that the frequency division by the Prescaler will be 1:1 and Postscaler will be 1:16. Second, let’s set TMR1=0 and PR2=255. Thus:
TIMER2 COUNT CALCULATION

The following simple C language program creates a delay of 1 sec using TIMER2:
TIMER2 one second delay program 











Tuesday, December 27, 2011

USB Communication...


USB Communication...

The USB interface is heaven for the users... mostly plug and play... or simply install the driver and everything would be working from there on... After short journey into USB, I realized it was a far jump from the RS232 I'm used to.

My learning points:

1. USB devices must have some intelligence built in. When you connect a device to a serial port, windows does not do anything UNTIL you tell it do so. Remember the old days when you connect a serial modem? You have to tell windows you have connected a serial modem and then install the necessary driver and then you can start using it by telling windows the comm port, baud rate, etc.

2. With USB, the moment you plug it that device, windows knows that a USB device has been connected. It will automatically try to identify the device and 'configure' it for use. If it fails to find a suitable driver or if it fail to properly communicate with the device, then it will complain... asking you for the driver or simply state that the USB device fails to be recognized.

3. When windows detect a USB device connection (pull up resistor on the data line)... it will query the device for its' class (mass storage, HID, etc). If the driver for the class is already available to windows then it will just install the driver and the device is ready for use...

4. SO, if you want you PIC to talk to the PC via USB... several key things need to be understood and programmed for...
** Your PIC must comply to the USB-bus strict timing requirement... for full speed USB, the timing is based on 48MHz clock... the USB portion of your PIC must operate at that speed, the main controller can operate at lower speed...
** Your PIC must response to PC initial queries (also called USB enumeration) to exhange various information in order for windows to recognise the device and use it...
** Your PIC USB portion must have what's called VendorID and ProductID in order for windows to manage USB communication destined for your device...
It is intended for transmission of data from a master device to/from one or more slave devices over short distances at high speeds (MHz).

It is simply based on an 8 bit shift register shifting data out on a single pin and shifting data in on another pin.

Note: some devices use more than 8 bits!

Its main use is to replace parallel interfaces so you don't have to route parallel buses around a pcb. pic spi masterFor example you can buy an SPI 12bit ADC and instead of 12 parallel wires to read the data you only need 4 SPI connections. Actually you may only need three as you may not need to send data to the device!


With the SPI interface you can communicate with a device transmitting and receiving 8 bits of data at the same time and it is suited to high speed streaming data transfers.


Note: The trade off between usingpic spi slave a parallel interface and the SPI interface is speed e.g. if you read a parallel 12bit ADC at 200ksps then you could read the device at a 200kHz rate but if you want to get the same data rate using SPI then you need a serial speed of 200kHz x 12 = 2.4MHz. So the actual trade off is speed and the consequential noise introduced into the circuit.

Unlike I2C there is no concept of transferring ownership of the bus i.e. changing bus master and there are no slave device addresses. SPI is a much simpler protocol and because of this you can operate it at speeds greater than 10MHz (compared with the 3.4MHz maximum for I2C).

The best feature of SPI is that you can do full duplex data transfers (data in both directions at the same time) which you can not do with I2C and you can do it fast.

Note: The maximum rate for a PIC Micro using a 20MHz clock is 5MHz.
SPI Interface : Signals
SPI Interface Signals
PIC name Master Slave
SCK Serial clock output from master [SCK] Input to slave [SCK]
SDO Serial data output from master [MOSI] Input to slave [MOSI}
SDI Serial data input from slave [MISO] Output from slave [MISO]
SS Optional slave (chip) select [SS]
Slave select [SS]

[] denotes SPI naming convention

Here is the setup for a single SPI device connection:

SPI Interface - single device

Single SPI device
Note: The chip select signal SS is optional for a single device system as you could tie the SS input at the slave low if the other lines are dedicated to SPI use.

There are two ways to implement multiple slave operation:

* Use a separate chip select for each slave device.
* Wire all the slaves together DataOut to DataIn (daisy chain).

SII Interface : Using chip selects

SPI Interface using separate chip selects



















With this scheme you control each slave device using its chip select line (usually active low- red arrows show control lines). When disabled the Data output from the slave goes into a high impedance state so it does not interfere with the currently selected slave and the data input is ignored (check datasheet).

The advantage of this scheme is that you can consider each device separately when you compare it with the daisy chain method.



SPI Interface : Daisy chaining

SPI interface with daisy chain



















With this scheme all data sent by the master is shifted into all devices and all data sent from each device is shifted out to the next (shown by red dotted arrow). For this scheme to work you have to make sure that each slave uses the clock in the same way (see clock and data) and you have to get the right number of bits - so there is more work to do in software.

Compared to I2C these are very inelegant slave selection mechanisms and look like kludges to get round the fact that SPI was designed really as a simple single master to single slave protocol. Having said that the above methods will work but for daisy chaining you will have to be careful of clock polarity and clock use as this is not defined in the SPI standard.
SPI Interface : Clock and Data
How a device reacts to clock input is undefined!!!

Data can be sampled at the rising or falling edge and data can be generated after the rising or falling edge!

This is why you can set the clock output from a master mode device in multiple ways just look at the diagram below - the first four signals are the four options you have to select the output clock.

SPI Interface PIC signals (extract from DS39582B)

PIC SPI interface signals



















You match the output clock to the clock that your device requires.

Note: This is why daisy chaining may not be a good idea (or you have to think very carefully about it!).

Note: For Master or Slave mode when using PICs you need to set the TRIS direction of the SCK pin appropriately.
Problems with the SPI interface

* The clock scheme may not be the same between devices.
* The data length can vary from device to device.

Advantages of the SPI interface

* Very fast > 10Mhz.
* Simple protocol (easy to program in software if you have no SPI hardware module).
* Simple interface (no bidirectional pins c.f. I2C).
* Supports full duplex data streaming.
Wireless System Overview

Over the next few weeks, we are going to develop a wireless system to capture and log data from remotes sensors. The system will have a master controller to manage the communication between all the devices (nodes) in the system.

Depicted above is the overall architecture and the communication mode.
The PC will be communicating with the master controller (mPIC) via the USB interface.
The master controller (mPIC) will be talking to the wireless module (RFM) via SPI interface.
The wireless module (RFM) will communicate wireless to another RFM using radio waves at 430MHz.
The slave (sPIC) will be talking to the RFM via SPI to receive commands and submit data.
The slave (sPIC) will be connected to various analog and digital sensors as required.

System general info.
The slave will be operating using batteries thus will be in sleep mode until communication/data capture is required.
The master controller will operate autonomously independent of the PC. The PC connection is required only for offloading of capture data for further storage or analysis as well as for initial setup and configuration of the system.

TUESDAY, JUNE 23, 2009

SPI Communication...

As per Wikipedia... (click link for extensive explanation)

"The Serial Peripheral Interface Bus or SPI (often pronounced "es-pÄ“-Ä«" [IPA: É›s pi: 'aɪ] or "spy" [IPA: spaɪ]) bus is a synchronous serial data link standard named by Motorola that operates in full duplex mode. Devices communicate in master/slave mode where the master device initiates the data frame. Multiple slave devices are allowed with individual slave select (chip select) lines. Sometimes SPI is called a "four wire" serial bus, contrasting with threetwo, and one wire serial buses."

Saturday, December 3, 2011

6 Digits 7-Segment LED Multiplexing using a Shift Register

Multiplexing technique can reduce number of needed I/O pins of the MCU as I have explained in 'LED 7-Segment Multiplexing' and '6 Digits LED 7-Segment Multiplexing'. In those posts, I used 13 I/O pins for driving 6 digits LED 7-Segment. However, the PIC16F627A and PIC16F628 have only 15 usable I/O pins that include 2 pins for external 32.768KHz oscillator. So, there is no pin left for time setting buttons. I can change to the PIC that has more I/O pins, but I don't think it's a good solution. From my searches, I can overcome this I/O pins shortage problem by using shift register to expand the MCU I/O pins.

The concept is very similar to led dot matrix driving technique. Each digit is multiplexed via a shift register 74HC595 which is required 3 pins of the MCU. Each segment of the 7-segment display is driven by PORTA of the PIC16F628. As a result, the required pins for driving 6-Digit 7-Segment display are just 3+7 = 10 pins!. With this configuration, there are 3 I/O pins that are free for time setting buttons and driving blinking second LEDs.

I use TMR2 module for scanning digits. TMR2 is an 8-bit timer which overflows every 256 (0xFF) counts. It's known that the refresh rate above 50Hz would be enough for human's eyes to see the display without recognizing the flickering. If I set TMR2 with 1:8 Prescaler (T2CON = 0x3C), the multiplexing frequency will be 81.3Hz (4MHz/4/256/8/6 = 81.3Hz) which is enough for flicker free display.

PORTA is used to drive each segment of the 7-segment displays. However, I have to skip the RA5 as it's a MCLR pin and it can be only input pin. So, my 7-segment digit mask is different then the normal 7-segment digit mask.

my PORTA 7-segment digit mask : {0x5F, 0x06, 0x9b, 0x8f, 0xC6, 0xCd,0xDD, 0x07,
0xDf, 0xCf}
Normal 7-segment digit mask : {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f} for number 0-9 respectively.


Below is the example schematic of 999999-second counter using the PIC16F627A or PIC16F628 and a shift register. I will not implement a clock with this configuration as I need more free MCU pins for driving Alarm buzzer and other things.

pic16F627a PIC16F628 74HC595 LED 7-segment multiplex

The source code for 999999-second counter in MikroC is listed below

//PIC16F627A or PIC16F628
//4MHz Internal OSC
//MUX by using Shift Register 595
// Critical parameters:
// Delay, Postscaler, Prescaler
// Low delay + High Prescaler
// 03/11/2008
// punkky@gmail.com
#define SH_CP PORTB.F0
#define DS PORTB.F1
#define ST_CP PORTB.F2
// 7-Segment code is skipping RA5, so the code is not as normal 7-segment coding
unsigned short number [10] = {
    0x5F0x060x9b0x8f0xC60xCd, 0xDD0x07,
    0xDf, 0xCf
};
unsigned short digit [6] = {
    000000
};
unsigned short i;
unsigned short n;
unsigned short counter;
unsigned short tick;
unsigned short shift_register;
unsigned short x1;
unsigned short x2;
unsigned short x3;
unsigned short x4;
unsigned short x5;
unsigned short x6;
void interrupt ()
{
    if (PIR1.TMR2IF)
    {
        PIR1.TMR2IF = 0;
        if (counter == 5)
        {
            //Shift data
            DS = 0;
            //Store data
            SH_CP = 1;
            SH_CP = 0;
            Delay_us (250);
            counter = 0;
        }else
        {
            //Shift data
            DS = 1;
            //Store
            SH_CP = 1;
            SH_CP = 0;
            Delay_us (250);
            counter ++;
        }
        ST_CP = 1;
        ST_CP = 0;
        PORTA = 0x00;
        PORTA = number [digit [counter]];
    }
    if (PIR1.TMR1IF)
    {
        TMR1H = 0x80;
        PIR1.TMR1IF = 0;
        tick = 1;
        x6 ++;
        if (x6 > 9)
        {
            x6 = 0;
            x5 ++;
            if (x5 > 9)
            {
                x5 = 0;
                x4 ++;
                if (x4 > 9)
                {
                    x4 = 0;
                    x3 ++;
                    if (x3 > 9)
                    {
                        x3 = 0;
                        x2 ++;
                        if (x2 > 9)
                        {
                            x2 = 0;
                            x1 ++;
                            if (x1 > 9)
                            {
                                x1 = 0;
                            }
                        }
                    }
                }
            }
        }
    }
}
void main ()
{
    //Digital I/O for PORTA
    CMCON = 0x07;
    TRISA = 0x00;
    PORTA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
    //Internal Clock 4MHz
    PCON.OSCF = 1;
    counter = 0;
    // Set GIE, PEIE
    INTCON = 0xC0;
    //1:8 post scaler
    T2CON = 0x3C;
    // enable interupt
    PIE1.TMR2IE = 1;
    T1CON = 0x0F;
    //Initial value TMR1: 0x8000
    TMR1H = 0x80;
    TMR1L = 0x00;
    // enable interupt
    PIE1.TMR1IE = 1;
    //Data
    DS = 0;
    //Store
    SH_CP = 0;
    ST_CP = 0;
    x1 = 0;
    x2 = 0;
    x3 = 0 ;
    x4 = 0;
    x5 = 0;
    x6 = 0;
    while (1)
    {
        if (tick)
        {
            tick = 0;
            digit [0] = x1;
            digit [1] = x2;
            digit [2] = x3;
            digit [3] = x4;
            digit [4] = x5;
            digit [5] = x6;
        }
    }
}