Search

Saturday, April 16, 2016

PIC ICSP Header Connection (PIN OUT)


Details of PIC ICSP and how to use it for pic microcontrollers.

PIC ICSP gives you a convenient way of programming PIC Micros without removing the chip from the development or production board.


Note: ICSP stands for In Circuit Serial Programming.

All you need is a programmer that provides the ICSP connector (usually a six pin molex/dupont connector) which you plug into your target board. For example PicKit2/Pickit3 uses the ICSP connections shown in the diagrams below. .

The programmer is controlled from the PC using an IDE and for the PicKit2/3 this will be MPLAB X IDE. This program loads up your hex file (that you want to burn into the PIC device) and sends commands to the programmer to do that job via the ICSP signals that you connect to your PIC device (see below).



Note: Older programmers that are labelled Serial or Parallel both send serial data to the PIC microcontroller through the PIC ICSP circuit. The 'Serial' or 'Parallel' description refers only to the interface used from the PC to the PIC ICSP circuit. Modern programmers such as the PicKit2/3 use a USB port. Again, a USB programmer is merely referring to the PC interface and the output at the ICSP connector is exactly the same as all the others.


Here a PIC ICSP and full reset circuit :

Note: This is for the 16F877 and other 40 pin chips that have the same pinout for the ICSP connector e.g. 18F2550 (or at least MCLR at top left and PGD and PGC at top right).






Notes on the above circuit:

The PIC ICSP reset circuit is an over the top over-protected circuit that you would use if you were being ultra cautious or producing a developed PCB design. It stops high volts going back to the 5V power line (D2), has a fast shut down when 5V is off (D1) - allows fast rest from power Off-to-On and has a defined rise time for a delayed reset start.

As you can see pin 6 on the ICSP connector - the PGM connection - is not connected. PGM is a specialised programming control pin, useful only in a production environment, and is used for low volt programming (See Section below on PGM). PIC chips come with the PGM interface enabled so that a PIC chip can be inserted into a production board and can be programmed by another device at the system level voltage. So you could have a situation where several PIC devices are connected to a master device and are re-programmable in the unit possibly over the web etc.

The important point is that a high voltage programmer such as a PICKit2/3 can always override the PGM interface and program the chip regardless of whether the PGM input is high or low and for single board use you set the PGM control inactive - this is a setting within the programming software such as MPLAB X etc. If the LVP mode is not turned off then the pin is not usable as normal I/O it can only be used for PGM signal.

Simplified PIC ICSP Connection

Here is a simplified ICSP connection for lab development:


Note: When you develop a board quickly e.g. on a solderless breadboard you only really need a 10k pullup from MCLRn to 5V - sometimes you will program that pin as an input in which case the reset is handled internally. With the 10k only; When programming, Does it put high voltage against the 5V? - Yes, however - the lab bench PSU will be fine (since there is (13V-5V)/10k ~ 10/10k = 0.1mA flowing)! - Put a diode in if you really want (you do loose 0.6V though).

Alternatively turn off the PSU and power the chip from the PicKit3 (the power setting is in MPLAB X IDE).

PIC ICSP Signals

PIC ICSP provides 6 connections from the pic ICSP programmer to your board as follows :
1. VPP (or MCLRn) Programming voltage (usually 13V).
2. Vcc Power (usually 5V).
3. GND Ground (zero volts).
4. PGD - Data usual port and connection RB7.
5. PGC - Clock usual port and connection RB6.
6. PGM - LVP enable usual port and connection RB3/RB4.


Note: With the connections made in this order on the connector it will not matter if the connector is placed the wrong way round as GND and VCC are then applied to clock and data. If VCC and GND had been at opposite ends of the connector then there would be a problem.
Note: The above ICSP signals are pin-ordered in the 
same way as the standard PicKit2/3 = good!
VPP Signal (Signal a programming action)

Vpp connects to the reset input of the pic microcontroller labelled MCLR. During programming or verify this signal is raised to the programming voltage (13.5V) - or VCC+3.5V. This signals to the microcontroller that programming/verification is about to start and for older parts, supplies current.

Note: Older pic micros used this line to directly power the programming circuit that updates the Flash memory. So this connection had to supply some current. With the newer parts that allow LVP (Low Volt programming) the programming voltage is generated internally so the Vpp signal from the pic ICSP is only used as an indicator i.e. it doesn't have to supply current.
VDD/VCC Signal (Power)

This connection may supply power to your board - usually using a 5V regulator (probably a 7805). This is ok for some use as you can develop a prototype board without needing any other power supply (just a power brick that plugs into the pic programmer circuit).

The only problem with it is that the programmer circuit is not designed for your circuit (does it have a heatsink) and it can also introduce noise to your circuit. If the programmer uses a 78L05 then you will only get 100mA maximum current output.
GND Signal

The ground reference - 0V.
PGC and PGD Signals (Clock and Data)

These are the signals that do the work. Data (PGD) and clock (PGC) transmit data to the pic micro. First data is sent either high or low voltage (0/1). After a suitable time the clock is strobed low to high - rising edge clocking the data into the microcontroller.

PGD is also the line driven by the pic micro during verify i.e. it is bi-directional.
PGM Signal (Low volt programming signal)

You do not need to worry about this pin - it is for Low Volt Programming (see below).

The purpose of this pin (on the ICSP connection) is to hold PGM low so the microcontroller does not enter LVP mode. It will usually be done using a pull down resistor e.g. 10k.

Note: If you program the microcontroller with LVP mode off then this signal will have no effect.

Note: PIC microcontrollers shipped with LVP enabled - so if you use a brand new chip you can use it in LVP mode. The only way to change the mode is by using a high voltage programmer.
Notes on the LVP (PGM) pin

It is there in case you use a device that is enabled for LVP - low volt programming. Basically when you use a new device that has never been programmed before LVP programming is enabled by default (p58, p148 - 16F88 datasheet DS30487C) so the resistor holds LVP mode off (low). This is implied in other datasheets and not specifically stated e.g. for the 18F2550.

However in MPLABX If you program the chip using a project file (from the on site projects) it is turned off anyway because I turned it off in MPLABX project settings. Once programmed off it is never turned on again unless you change it in a compiler project setting.

You can forget about PGM especially if you have programmed the chip for the 1st time using a high-volt programmer (e.g. pickit3). Remember you can always program the device regardless of the LVP setting using a high-volt programmer i.e. LVP is an additional feature. If the LVP mode is not turned off then the pin is not usable as normal I/O it can only be used for the PGM signal - which is why you really want to turn it off.
What is LVP for?

The purpose of LVP is to allow complete programming using only Vcc i.e. 5V and no higher voltage and that means you don't have to have a dedicated power supply voltage e.g. 12 V to program the device. i.e. you could program multiple devices on a board from one central microcontroller using LVP.

The actual LVP control is in the CONFIG1 register ( p130 16F88 datasheet DS30487C - probably different for other devices) so it is either set in the IDE (MPLABX etc.) or using a #pragma directive (see your compiler documentation).

Note: You can only program the LVP bit off using a high volt programmer.
Note: There are other ways to program on-board-chips e.g. by using a bootloader.- in short you use a high-volt programmer to load a small program that listens to a port for a short while - if a code is received then it enters programming mode listening for received data and programming that into the program area of the device, A port can be any comms interface e.g. USB,ethernet, SPI,I2C but is more commonly RS232. This method is used for many systems commonly popular in Arduino and PICAxe.

Using LVP means you do not need a bootloader so valuable program memory is saved - but you have to arrange the hardware to do it..
What circuit do you need on your target board?

Note that the diagram from pic ICSP application note 'DS33023A' specifically goes out of its way to not design it for you saying RB6 and RB7 should be isolated but this depends on your circuit! This is not very helpful so I have included the circuit I use on my development board (See the diagram shown earlier):

To ensure you can program and verify correctly two 10k resistors isolate the programmer (and RB6 and RB7) from the rest of the circuit i.e. they stop signals at the other side from interfering with RB6 and RB7 during programming. If you don't use the isolation resistors then loading or driving the pins can stop programming all together.

For example if you put an LED on RB6 (PGD) that draws 20mA when on. The output voltage (when the output is on) will be pulled so low that the pic ICSP programmer will not be able to read back the desired voltage i.e. it will give a verification failure.



PIC18F Configuration Setting in MPLAB X


How Configuration Bits are set

Each PIC® MCU has it's own set of configuration bits. The Special Features section of the individual datasheets contains the definition for each of the bits.

The setting for each configuration bit is determined by directives written in the application software. The syntax for the configuration bit settings is available from the compiler manual. This tutorial will show how to generate proper configuration code without consulting the compiler manual for the proper syntax.
How to display the Configuration Bits window


From the main menu select Window ▶ PIC Memory Views ▶ Configuration Bits



The Configuration Bits window will open in a tab in the Output area under the editor.


How to set configuration bits and generate initialization code


1


In the configuration bits window, click on any value in the Option column and it will turn into a combo box that will allow you to select the value you desire.

The example on the left shows the WatchDog timer being changed from "enabled" to "disabled"



2


Click on the Generate Source Code to Output button:



3


The IDE will automatically generate the code necessary to initialize all the configuration bits to the settings you specified in the window. This code may now be copied and pasted into one of your source files, or you may save it to its own file and add it to your project. To save the file, right click anywhere in the output window and select Save As from the popup menu as shown in the screenshot at left.

Saturday, March 5, 2016

ADC Interrupt in PIC18

Program:

//Author : Palak Patel
//Contact No:9173211683
//Title:usart transmission and receiver
//Platform: PIC18f4520
//Software:MPLAB

//Configuration Bits
//**********************************************************************************
#include<p18f4520.h>
//#pragma config OSC = INTIO67
//#pragma config FCMEN = OFF
//#pragma config IESO = OFF
//#pragma config PWRT = OFF
//#pragma config BOREN = OFF
//#pragma config WDT = OFF
//#pragma config MCLRE = ON
//#pragma config PBADEN = OFF
//#pragma config STVREN = OFF
//#pragma config LVP = OFF
//Includes
//**********************************************************************************
static volatile int x,y,c=0x100,z, result;

void ADC_Conversion(unsigned int ADC_Value);

#define LCD PORTC
#define Stepper PORTD
void LCD_Ini();
void LCD_cmd(unsigned char);
void LCD_dat(unsigned char);
void LCD_Display(unsigned char lcd_pass[]);
void Delay_ms(unsigned int);
void Stepper_Motor(unsigned char);

//start ISR code
#pragma code isr = 0x08                                  // store the below code at address 0x08
#pragma interrupt isr                                       // let the compiler know that the function isr() is an interrupt handler
void isr(void)
{
if(PIR1bits.ADIF == 1)
  {
    PIR1bits.ADIF = 0;
    ADCON0bits.GO_DONE = 0;
    z = ADRESL + (ADRESH * c);
ADC_Conversion( z );
       }
}

void main(void)
{
      unsigned char name[] = "Palak Patel";
TRISA = 0xFF;                
       TRISC = 0x00;              
TRISD = 0x00;
    LCD_Ini();
ADCON1 = 0x0E;
       ADCON2 = 0xBE;    
    ADCON0 = 0x01;    
 
       LCD_cmd(0x80);
       LCD_Display(name);
    Delay_ms(2000);

RCONbits.IPEN   = 0;                 // Disable interrupt priority
    INTCONbits.GIE  = 1;                 // Global enable interrupts
INTCONbits.PEIE = 1;                // enable peripheral interrupts.
       PIR1bits.ADIF = 1;               //An A/D conversion completed (must be cleared in software)
    PIE1bits.ADIE = 1;               //Enables the A/D interrupt
 
    //ADCON0bits.GO_DONE = 1;
    while(1)
    {
 
    }
}

void ADC_Conversion(unsigned int ADC_Value)
{
unsigned char Adc_data[5];
LCD_cmd(0xc0);
  Adc_data[0] = (ADC_Value/1000) % 10;
LCD_dat(48 + Adc_data[0]);
    Adc_data[1] = (ADC_Value/100) % 10;
LCD_dat(48 + Adc_data[1]);
        Adc_data[2] = (ADC_Value/10) % 10;
LCD_dat(48 + Adc_data[2]);
         Adc_data[3] = ADC_Value % 10;
LCD_dat(48 + Adc_data[3]);
ADCON0bits.GO_DONE = 1;
}

void LCD_Ini()
{
LCD_cmd(0x01);                          //Clear Lcd
       LCD_cmd(0x02);                          //4 Bit Specification
       LCD_cmd(0x28);                          //4 Bit specification
       LCD_cmd(0x0c);
       LCD_cmd(0x80);                          //Cursor starting point
       LCD_cmd(0X06);
}

void LCD_cmd(unsigned char k)
{
        LCD &= 0x0F;
        LCD |= (k & (0xF0));
        LCD |= (2<<0);
        Delay_ms(2);
        LCD = LCD & 0xFC;
        Delay_ms(20);

        LCD &= 0x0F;
        LCD |= ((k<<4) & (0xF0));
        LCD |= (2<<0);
        Delay_ms(20);
        LCD=LCD & 0xFC;
        Delay_ms(20);
}
void LCD_dat(unsigned char k)
{
        LCD &= 0x0F;
        LCD |= (k & 0xF0);
        LCD |= (3<<0);
        Delay_ms(20);
        LCD = LCD & 0xFD;
        Delay_ms(20);

        LCD &= 0x0F;
        LCD |= ((k<<4) & (0xF0));
        LCD |= (3<<0);
        Delay_ms(20);
        LCD = LCD & 0xFD;
        Delay_ms(20);
}
void LCD_Display(unsigned char lcd_pass[])
{
unsigned char i = 0;
while(lcd_pass[i] != '\0')
{
LCD_dat(lcd_pass[i]);
Delay_ms(20);
i++;
}
}

void Delay_ms(unsigned int p)
{
unsigned int i,j;
for(i=0;i<p;i++)
{
for(j=0;j<20;j++);
}
}

void Stepper_Motor(unsigned char status_value)
{
if(status_value == 1)
{
Stepper=0x01;
Delay_ms(1000);
Stepper=0x02;
Delay_ms(1000);
Stepper=0x04;
Delay_ms(1000);
Stepper=0x08;
Delay_ms(1000);
}
else
PORTD = 0x00;
}

PIC 18F UART Receiver and Transmitter

Program:

//Author : Palak Patel

//Contact No:9173211683
//Title:usart transmission and receiver
//Platform: PIC18f4520
//Software:MPLAB

#include<p18f4520.h>

#pragma config OSC = HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOREN = OFF
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config PBADEN = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF

#define LCD PORTD

#define RS PORTCbits.RC0
#define RW PORTCbits.RC1
#define EN PORTCbits.RC2

// start ISR code

#pragma code isr = 0x08                                  // store the below code at address 0x08
#pragma interrupt isr                                          // let the compiler know that the function isr() is an interrupt handler

void delay();

void cmd(unsigned char);
void dat(unsigned char);
void Delay_ms(unsigned char);

void isr(void)

{
   unsigned char lcddata;
   if(PIR1bits.RCIF == 1)                              // if the USART receive interrupt flag has been set
   {
       if(PIR1bits.TXIF == 1)                    // check if the TXREG is empty
       {
            lcddata=RCREG;
dat(lcddata);
          }
   }    
}

void main()

{
              unsigned char palak[]="Palak Patel";
              unsigned int i=0;

TRISCbits.TRISC0=0;
TRISCbits.TRISC1=0;
TRISCbits.TRISC2=0;
             TRISCbits.TRISC6 = 0;                 // make the TX pin a digital output
    TRISCbits.TRISC7 = 1;                 // make the RX pin a digital input
TRISD=0x00;

cmd(0x01);                          //Clear Lcd

          cmd(0x02);                          //4 Bit Specification
          cmd(0x38);                          //4 Bit specification
          cmd(0x0c);
          cmd(0x80);                          //Cursor starting point
cmd(0x06);
           
          TXSTAbits.CSRC=1;               //Master Mode
          TXSTAbits.TX9=0;                   //8 Bit
          TXSTAbits.TXEN=1;                //Transmit enabled
          TXSTAbits.SYNC=0;                //Asynchronous Mode
          TXSTAbits.SENDB=0;             //Sync Break transmission completed
          TXSTAbits.BRGH=1;               //High Speed
      RCSTA=0x90;
SPBRG=100;   


RCONbits.IPEN   = 0;                 // disable interrupt priority
    INTCONbits.GIE  = 1;                 // enable interrupts
    INTCONbits.PEIE = 1;                // enable peripheral interrupts.
    PIE1bits.RCIE   = 1;                    // enable USART receive interrupt

                while(palak[i]!='\0')

                {
                                while(PIR1bits.TXIF==0);// TMRT Empty
                                TXREG=palak[i];       //Transmit buffer
                                i++;
                }
while(1);
}

void delay()

{
                unsigned int j;
                for(j=0;j<100;j++);
}

void cmd(unsigned char k)

{
        LCD=k;
        RS=0;
        RW=0;
        EN=1;
        Delay_ms(20);
        EN=0;
}

void dat(unsigned char k)

{
        LCD=k;
        RS=1;
        RW=0;
        EN=1;
        Delay_ms(20);
        EN=0;
}

void Delay_ms(unsigned char p)

{
unsigned char i,j;
for(i=0;i<p;i++)
{
for(j=0;j<20;j++);
}
}

Tuesday, November 3, 2015

SAMD21 Features

  • SAMD21J18A microcontroller
  • One mechanical reset button
  • One mechanical user pushbutton (wake-up, bootloader entry or general purpose)
  • One yellow user LED
  • 32.768kHz crystal
  • USB interface, device and reduced host mode
  • 8 Mbit Serial Flash
  • 3 Xplained Pro extension headers
  • Embedded Debugger
    • Auto-ID for board identification in Atmel Studio 6.1
    • One yellow status LED
    • One green board power LED
    • Symbolic debug of complex data types including scope information
    • Programming and debugging
    • Data Gateway Interface: SPI, I²C, 4 GPIOs
    • Virtual COM port (CDC)
  • USB powered
  • Supported with application examples in Atmel Software Framework

Samd21 Firmware Upgrade(Edbg)

Operation modePower LEDStatus LED
Normal operationPower LED is lit when power is applied to the board.Activity indicator, LED flashes every time something happens on the EDBG.
Bootloader mode (idle)The power LED and the status LED blinks simultaneously.
Bootloader mode (firmware upgrade)The power LED and the status LED blinks in an alternating pattern.
1->   C:\Users\xxxxx\Documents>atfw -h


Usage: atfw [options] [arguments]

Options:
  -a, --archive .zip
                                 Archive containing firmware upgrade image.

  -h, --help                     Display help information.

  -l, --list                     List connected tools.

  -i, --id                       Print boot loader id (edbg only).

  -t, --tool                Tool name: edbg, medbg, avrone, jtagicemkii, jtagice3
                                 stk600, qt600, avrispmkii or avrdragon.

  -s, --serialnumber        The programmer/debugger serial number.

  -q, --quiet                    Do not display activity indicator.

  -V, --version                  Display version number.

  -r, --read                     Read firmware version on tool.

  -n --nographics                No progress bar, but result alone will be displayed

Example:
  atfw -a myImage.zip -t jtagice3 -s 123456789ABC


2-> C:\Users\xxxxx\Documents>atfw -t edbg -a "C:\Program Files (x86)\Atmel\Atmel Studio 6.2\tools\EDBG\edbg_fw.zip"
Found edbg:ATML2130021800001691
Waiting for bootloader usb enumeration: [==========]
Upgrading MCU: [==========]
Successful upgrade

Doubly Linked List

#include<stdio.h>
typedef struct node
{
    int data;
    struct node *next;
    struct node *prev;
}NODE;

NODE *start=NULL,*top,*temp;

void *Create_Node(int value);
void Insert_At_Last();
void Display_Start_To_End();
void Display_End_To_Start();
void Insert_At_Position();
void Delete_At_Last();
void Delete_At_Position();
void Search();
void Update_Value();
void Node_Count();


void main()
{
    int choice;
    while(1)
    {
        printf("\n ENTER CHOISE \n 1.INSERT AT LAST \n 2.Delete_At_Last \n                                         3.Insert_At_Position \n 4.Display_Start_To_End \n 5.Display_End_To_Start \n                                   6.Delete_At_Position \n 7.Search \n 8.Update_Value \n 9.Node Count \n 10.Exit \n");
        printf("\nEnter Your Choice:");
        scanf("%d",&choice);
        switch(choice)
        {
            case 1:
                Insert_At_Last();
                break;

            case 2:
                Delete_At_Last();
                break;

            case 3:
                Insert_At_Position();
                break;

            case 4:
                Delete_At_Position();
                break;

            case 5:
                Display_Start_To_End();
                break;

            case 6:
                Display_End_To_Start();
                break;

            case 7:
                Search();
                break;

            case 8:
                Update_Value();
                break;

            case 9:
                Node_Count();
                break;

            case 10:
                exit(0);

            default:
                printf("\nWrong Choice\n");
        }
    }
}

void *Create_Node(int value)
{
    NODE *new_node;
    new_node=(NODE *)malloc(sizeof(NODE));
    new_node->data=value;
    new_node->next=NULL;
    new_node->prev=NULL;
    return new_node;
}

void Insert_At_Last()
{
    int ch;
    NODE *new_node;
    printf("Enter The Data:-> ");
    scanf("%d",&ch);
    new_node=Create_Node(ch);
    if(start==NULL)
    {
        start=new_node;
        top=new_node;
    }
    else
    {
        top->next=new_node;
        new_node->prev=top;
        top=new_node;
    }
}

void Display_Start_To_End()
{
    NODE *temp;
    printf("Displaying List From Start to End:->\n");
    temp=start;
    while(temp!=NULL)
    {
        printf("%d \n",temp->data);
        temp=temp->next;
    }
}

void Display_End_To_Start()
{
    NODE *temp;
    printf("Displaying List From End to Start:->\n");
    temp=top;
    while(temp!=NULL)
    {
        printf("%d \n",temp->data);
        temp=temp->prev;
    }
}

void Insert_At_Position()
{
    NODE *new_node;
    int ch,pos,cnt=1;
    printf("\nEnter the Data:->");
    scanf("%d",&ch);
    new_node=Create_Node(ch);
    printf("\nEnter the position:->");
    scanf("%d",&pos);
    temp=start;
    if(pos==1)
    {
        new_node->next=start;
        start->prev=new_node;
        start=new_node;
    }
    else
    {
        temp=start;
        while(cnt<(pos-1))
        {
            temp=temp->next;
        }
        new_node->next=temp->next;
        temp->next->prev=new_node;
        new_node->prev=temp;
        temp->next=new_node;
    }
}

void Delete_At_Last()
{
    top=top->prev;
    top->next=NULL;
}

void Delete_At_Position()
{
    int pos,cnt=1;
    NODE *temp;
    printf("\nEnter the Position:->");
    scanf("%d",&pos);
    temp=start;
    while(pos<=(cnt-1))
    {
        temp=temp->next;
    }
    temp->next=temp->next->next;
    temp->next->prev=temp;
}

void Search()
{
    NODE *temp;
    int ch,cnt=1;
    printf("\nEnter the data to search:->");
    scanf("%d",&ch);
    temp=start;
    while(temp->next!=NULL)
    {
        if(temp->data==ch)
        {
            printf("\nData is at position:->%d \n",cnt);
        }
        temp=temp->next;
        cnt++;
    }
}

void Update_Value()
{
    NODE *ptr;
    int Old_val, New_val, flag = 0;
    printf("\n...Updating Node Value...\n");
    if (start == NULL)
    {
        printf("\nNo nodes in the list to update\n");
    }
    else
    {
        printf("\nEnter the value to be updated:->");
        scanf("%d", &Old_val);
        printf("\nEnter the newvalue:->");
        scanf("%d", &New_val);
        for (ptr = start;ptr != NULL;ptr = ptr->next)
        {
            if (ptr->data == Old_val)
            {
                ptr->data = New_val;
                flag = 1;
                break;
            }
        }
        if (flag == 1)
        {
            printf("\nUpdated Successfully");
        }
        else
        {
            printf("\nValue not found in List");
        }
    }
}

void Node_Count()
{
    int cnt;
    temp=start;
    while(temp!=NULL)
    {
        temp=temp->next;
        cnt++;
    }
    printf("\nNO.of Nodes In the list is =%d",cnt);
}