Showing posts with label Embedded. Show all posts
Showing posts with label Embedded. Show all posts

Saturday, 22 September 2012

Pics have Timers

PICs come with hardware counters know as timers. I have just been playing with its timer features using the PicKit3 demoboard. The diagram below is taken from the PIC tutorial I am following.


There are some interesting things to note:

  • The timer has a prescaler
  • TMR0IF is the output and it needs to be cleared when set.
  • There is a complex arrangement for reading TMR0H
The timer has a prescaler
The prescaler allows us to divide the timers clock. In the example below their are two line of code (one commented out) That set the value of the prescaler.

 // Init Timer
    INTCONbits.TMR0IF = 0;          // clear roll-over interrupt flag
    //T0CON = 0b00001000;             // no prescale - increments every instruction clock
    T0CON = 0b00000001;             // prescale 1:4 - four times the delay.
    TMR0H = 0;                      // clear timer - always write upper byte first
    TMR0L = 0;
    T0CONbits.TMR0ON = 1;           // start timer

 TMR0IF is the output and it needs to be cleared when set.
We need to clear the output of the timer before we start it. The counter can be started using T0CONbits.

There is a complex arrangement for reading TMR0H
The high byte of the timer is no directly accessible. It can only be accessed in conjunction with the lower bytes. To read the timer always read TMR0L first then TMR0H. To write to the timer always write to TMR0H first then followed by TMR0L.

Reference
MicroChip PICkit3 Debug Express, PIC18F45k20 - MPLAB C Lessons. 

Wednesday, 19 September 2012

Switch Input












This post looks at lesson 4 of the Pic tutorial.


/** D E F I N I T I O N S ****************************************************/
#define Switch_Pin      PORTBbits.RB0
#define DetectsInARow   5

The # define in the .h file can be used to define meaningful names to the SFR register.



#pragma udata   // declare statically allocated uinitialized variablesunsigned char LED_Display;  // 8-bit variable
#pragma code    // declare executable instructions
void main (void)
{
    unsigned char Switch_Count = 0;
    LED_Display = 1;            // initialize
    TRISD = 0b00000000;     // PORTD bits 7:0 are all outputs (0)     INTCON2bits.RBPU = 0; // enable PORTB internal pullups     WPUBbits.WPUB0 = 1; // enable pull up on RB0      ANSELH = 0x00;              // AN8-12 are digital inputs (AN12 on RB0)      TRISBbits.TRISB0 = 1;       // PORTB bit 0 (connected to switch) is input (1)
    while (1)
    {
        LATD = LED_Display;     // output LED_Display value to PORTD LEDs
        LED_Display <<= 1;      // rotate display by 1
        if (LED_Display == 0)
            LED_Display = 1;    // rotated bit out, so set bit 0

        while (Switch_Pin != 1);    // wait for switch to be released
        Switch_Count = 5;
        do
        { // monitor switch input for 5 lows in a row to debounce
            if (Switch_Pin == 0)
            { // pressed state detected                Switch_Count++;
            }
            else
            {
                Switch_Count = 0;
            }
            Delay10TCYx(25);    // delay 250 cycles or 1ms.        } while (Switch_Count < DetectsInARow);
    }
}

Some of the pins are shared with the analog input to the pic and hence need to be configured as digital. The C code above is also used to debonce the mechanical switch.

---

I decided to try my hand at some simple refactoring to make the code more readable.


/** V A R I A B L E S *************************************************/
#pragma udata   // declare statically allocated uinitialized variables
unsigned char LED_Display;  // 8-bit variable
unsigned char Switch_Count = 0;
/** D E C L A R A T I O N S *******************************************/
#pragma code    // declare executable instructions
void main (void)
{
    InitOutputs();
    InitInputs();
    while (1)
    {
        SetOutputLedAndRotate();
        DebounceSwitchDetect();
    }
}

void InitOutputs(void)
{
    LED_Display = 0b10101010;            // initialize
    TRISD = 0b00000000;     // PORTD bits 7:0 are all outputs (0)
}
 

void InitInputs(void)
{
    INTCON2bits.RBPU = 0; // enable PORTB internal pullups
WPUBbits.WPUB0 = 1; // enable pull up on RB0
    ANSELH = 0x00;              // AN8-12 are digital inputs (AN12 on RB0)
    TRISBbits.TRISB0 = 1;       // PORTB bit 0 (connected to switch) is input (1)
}


void SetOutputLedAndRotate(void)
{
     LATD = LED_Display;     // output LED_Display value to PORTD LEDs
     LED_Display <<= 1;      // rotate display by 1
     if (LED_Display == 0)
        LED_Display = 3;    // rotated bit out, so set bit 0
}
 
void DebounceSwitchDetect(void)
{
  while (Switch_Pin != 1);  // wait for switch to be released
        Switch_Count = 5;
        do
        { // monitor switch input for 5 lows in a row to debounce
            if (Switch_Pin == 0)
            { // pressed state detected
                Switch_Count++;
            }
            else
            {
                Switch_Count = 0;
            }
            Delay10TCYx(25);    // delay 250 cycles or 1ms.
        } while (Switch_Count < DetectsInARow);
}



Wednesday, 12 September 2012

My Pic Microcontroller has some LEDs


Lesson 1: Hello LED
This blog post looks at doing nothing more that turning on and off the LEDs connected to port D of the PicKit3 demo board.






#pragma config FOSC = INTIO67
#pragma config WDTEN = OFF, LVP = OFF, MCLRE = OFF
#include "p18f45k20.h"
void main (void)
{
TRISD = 0b01111111; // PORTD bit 7 to output (0); bits 6:0 are inputs (1) LATDbits.LATD7 = 1; // Set LAT register bit 7 to turn on LED
while (1);
}

The TRISD variable is used to access the tri-state for I/O on port D. LATDbits.LATD7 is used to access the seventh bit of port D. The code below uses  LATD instead of LATDbits.LATD7 to achiveve the same affect.


#pragma config FOSC = INTIO67
#pragma config WDTEN = OFF, LVP = OFF, MCLRE = OFF
#include "p18f45k20.h"
void main (void)
{
TRISD = 0b01111111; // PORTD bit 7 to output (0); bits 6:0 are inputs (1)
        LATD = 0x80; while (1);
}

Lesson 2: BLINK LED
Configuration bits are used to set operating modes of enable disable different features of the Pic. The code below uses the configurations bits to set features such as the watch dog timer and the type of oscillator used.


#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF     // CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30      // CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768      // CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC  // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF    // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF             // CONFIG5L
#pragma config CPB = OFF, CPD = OFF      // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF    // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF       // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF   // CONFIG7L
#pragma config EBTRB = OFF   // CONFIG7H
#include "p18f45k20.h"
#include "delays.h"
void main (void)
{
TRISD = 0b01111111; // PORTD bit 7 to output (0) ; bits 6:0 are inputs (1) while (1)
{
LATDbits.LATD7 = ~LATDbits.LATD7; // toggle LATD
Delay1KTCYx(500); // Delay 50 x 1000 = 50,000 cycles; 200ms @ 1MHz } }


The Delay1KTCYx(500) instruction is used to create a delay. The delay in this example is 200 ms and  is calculated as follows:

Delay = (No of Cycles to execute an instruction/Frequency)  x Delay in thousands of clock cycles x 1000

Delay = (4/1MHz) x 50 x 1000 = 200ms.

Lesson 3: Rotate LED

#pragma udata (uninitialized data) and #pragma idata (initialized data) are used to allocate memory for static variables in the file register. #pragma code  is used to indicate a section of instructions and #pragma romdata is used for constant data stored in program memory.


/** C O N F I G U R A T I O N   B I T S ******/                                       
/** I N C L U D E S **********************/
/** V A R I A B L E S ********************/#pragma udata // declare statically allocated uninitialized variablesunsigned char LED_Number;  // 8-bit variable
/** D E C L A R A T I O N S *******************************************/// declare constant data in program memory starting at address 0x180#pragma romdata Lesson3_Table = 0x180
const rom unsigned char LED_LookupTable[8] = {0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80};
#pragma code    // declare executable instructions
void main (void)
{
    LED_Number = 0;            // initialize    TRISD = 0b00000000;     // PORTD bits 7:0 are all outputs (0)
    while (1)
    {
// use lookup table to output one LED on based on LED_Number value        LATD = LED_LookupTable[LED_Number];  
        LED_Number++;      // rotate display by 1
        if (LED_Number == 8)
            LED_Number = 0;    // go back to LED 0.
        Delay1KTCYx(50);    // Delay 50 x 1000 = 50,000 cycles; 200ms @ 1MHz    } }




Reference
MicroChip PICkit3 Debug Express, PIC18F45k20 - MPLAB C Lessons.



Tuesday, 11 September 2012

I cant remember much about Pics


Harvard Architecture
The Microchip Pic microcontrollers are based on the Harvard Architecture. This means that the program and data memory are in separate address spaces i.e.  the each have their own address and data bus. In addition to program and data memory the stack also has its own dedicated memory which will allow 31 levels or subroutines.

Reset
On reset the address counter will be set to 0x000000. However the instruction placed at this address is normally a jump. The jump is used because the interrupt vectors sits at 0x000008 and 0x000018.

Memory Modes
Transparent to a C programmer the Pic can have two memory modes small and large and some areas program memory can be protected to keep your design from others eyes.

File Register
The Pic has between 4K and 8K of data memory, known as the File Register. The data is organised into 256k banks that can be accessed using a bank select register. There are areas in Bank0 and Bank15 that can be accessed without the need of swapping banks. This is known as Access Ram and contains the Special Function Registers. Again this is transparent to the C programmer.

Saturday, 28 April 2012

I've got a PICkit3


PICkit3 demo board
In my hand is the PICkit3 a small demo board from Microchip that includes a PIC18F45K20 microcontroller. The demo board itself is quite simple. It has three inputs a reset button (if you can call than an input), a single jumper switch and a variable resistor that is probably for playing with the ADC on the micro.

The PIC18F45K20
The PIC18F45K20 is a RISC based microcontroller that has 64kbytes of code space and 3936bytes of data space. It has been optimized to work with a C complier and is capable of speed of 16MIPS. It has a number of built in peripherals such as a  watch dog timer, ADC,  35 I/Os, PWM, I2C and a UART.

Why do I have it?
Apart from what I have discovered above I know very little about this microcontroller and has it been a little while since I have played with embedded electronics. My aim therefore over the next few weeks is to explore the features of this pic and record my results in this blog. Initially I will follow the tutorial that comes with the demo board than I will do something of my own. However the tutorial looks like it is mainly based around using the C compiler, but it is my view to get to know a micro we need to look at its architecture and play with some assembly code. So I also intend to do this as well.

I will leave you with a link to a YouTube video I stumbled across that gives some more information about the PICkit3. Enjoy!!!!!!!!!!!!!