Installing USBASP drivers on Windows 8 or 10 is bit tricky. As these versions of Windows require DEVICE DRIVER VERIFICATION , they do not allow unsigned drivers like libusb.
For programming 8051 or AVR you need this driver.
You can install by following methods :
1. Disabling Windows driver enforcement on boot up. Follow this link
This method requires SHIFT+ RESTART of Windows to enter advanced troubleshooting where we disable signature verification .After this you can install the libusb driver.
But in some laptops , this method fails on next Windows update.
2. Install libusb drivers using ZADIG application.
Zadig is meant to install a libusb compatible driver, for a device that does not yet have such a driver installed.
With the application running, you should see your USB device appear in the dropdown list
(click on the dropdown to see all devices).
You can also plug your USB device after Zadig is running, as the list is refreshed automatically. Its recommended to leave only the device you want to install a driver for, and unplug any other USB device.
You can also select the driver you want to install,( between WinUSB/libusb-win32/libusb0 / libusbK )
Once you are satisfied with the selection and device description, simply click the Install Driver Button.
Caution :
If you select the wrong device, Zadig will replace its driver.
The responsibility is entirely yours try to pay attention to the device you select .Don’t just press the install button on the first device you see,
If wrong driver is replaced , then some of your USB devices like wireless mouse may not work.
3. Best & Easy method
The USBASP windows driver was previously based on libusb-win32. The certificate on the base drivers have expired and the library has now been superseded by libusbK.
Following is the procedure to install protostack USBASP driver.
At first when you connect the USBASP hardware to PC & open the Device Manager you see an exclamation mark against USBASP indicating that drivers not installed.
If you open the PROGISP application ( to load HEX file on to8051) ,you see the PRG ISP icon greyed out ,as the programmer is not yet detected.
ATMEGA 16/32 has 3 TIMERS —TIMER0 8 bit , TIMER 1 (16 Bit) , Timer 2 (8 bit).
In the previous post we tested with TIMER0 .
This post is related to TIMER 1 , particularly the INTERRUPT functions.
As we know Timers work by incrementing a counter variable called counter register. The counter register can count to a certain value, depending on its size. The timer increments this counter one step at a time until it reaches its maximum value, at which point the counter overflows, and resets back to zero.
Since Timer1 is 16 bits, it can hold a maximum value of (2^16 – 1), or 65535.
In order to increment the counter value at regular intervals, the timer must have access to a clock source. The clock source generates a consistent repeating signal. Every time the timer detects this signal, it increases its counter by one.
If clock source is 8MHz we’ll go through one clock cycle every 1 / 8000000 seconds, or 0.000000125 secs or 0.125 usec . That means Timer1 Counter takes 65535 * 0.000000125 = 0.0082
timer counts will elapse in 0.0082 secs
So , if we need a one second delay ( 1000msec) , 1000/0.0082 = 121951 which obviously higher than 65535 which is the highest count for TIMER1.
Here comes the need of PRESCALER
Clock source can be divided by 8 , 64, 256 , 1024 by setting the bits 0:2 of TCCR1B
After counting 65535 , The timer normally sets a flag (OverFlow Flag) bit to let you know an overflow has occurred.
In case of TIMER1 , COUNTER Register is made of 2 , 8 bit Registers TCCR1A & TCCR1B put together forms a 16 bit Register
You can check this flag manually, or you can also have the timer trigger an interrupt as soon as the flag is set. You can specify an Interrupt Service Routine (ISR) to run code of your choice when the timer overflows. The ISR will reset the overflow flag behind the scenes,
Following table shows the list of REGISTERs associated with TIMER1
TCCR1 is actually composed of two registers TCCR1A & TCCR1B
TCCR1A controls the compare modes & the pulse width modulation modes
TCCR1B COUNTER SELECT bits 0:2 control the input to Timer1 .These 3 select bits provide clock signals that are absolutely identical to those of Timer0
When the timer counts past 65535 (0xFFFF) , it sets the Flag TOV1 (bit 2 of TIFR ) register.The registers TIFR & TIMSK are common for all 3 timers.
When Compare register is used , the OCF1B or OCF1A flag is set according to the channel (A or B) used for Compare operation.
Instead of manually checking the Flags in TIFR , Interrupts can be used to trigger ISR automatically when the particular Interrupt bit is Enabled in TIMSK register.
As seen below bits 2 to 5 are for TIMER1
If TOIE1 bit is enabled , on Timer 1 overflow , the corresponding Interrupt Service Routine ISR is called automatically & the code inside ISR is executed
Following is the list of Vector table.You have to use the correct VECTOR NAME in the ISR Function
From above table you can see RESET is on the top of table & is unmaskable ,having the highest priority
if Timer overflow interrupt TOIE1 is enabled , You need to use the ISR function Vector 9 in table
First example code is using OVERFLOW INTERRUPT.
Using this interrupt we blink an LED connected to PD6 – pin 20
We use the external crystal 8MHZ as clock source. ( High FUSE 0XD9 , LOW Fuse 0XFD)
To start with include the 2 Header files at the top of code.
Inside the Main Function PD6 pin is made as OUTPUT , as we’ve connected an LED at pin20.
DDRD |= (1<<6);
The prescaler we’ve selected is 256 .To apply this we need to set the bit CS12 in the TCCR1B register.In Timer1 the control register is of 2 parts TCCR1A & TCCR1B .
Prescaler select bits are found in TCCR1B.
TCCR1B |= (1<<CS12); // prescaler 256 selected , clock is now 8000000/256= 31250Hz
Next load the TCNT1 counter with the calculated value
TCNT1 = 49910;
Calculation is as follows :
Suppose we want to blink the LED at at the rate 2HZ , i.e., 0.5sec ( 500 milli secs) interval
We selected prescaler 256
The clock frequency becomes 8000000 / 256 = 31250 Hz
Time for each Tick is 1 / 31250 = 0.000032 sec = 32usec
For 500 msec to elapse the count is 500 / 0.032 = 15625
Timer 1 counts from 0 to 65535 & overflows.
65535 – 15625 = 49910
So if you preload the counter with 49910 , the counter starts at 49910 & counts up to 65535 elapsing 15625 count & creating 500 msec delay
Next enable the Timer OverFlow Interrupt TOIE1 in the TIMSK Register
TIMSK |= (1<<TOIE1);
Enable the Global Interrupt using the command
sei();
Now we’ve to write the code for ISR with correct vector name TIMER1_OVF_vect
Inside the ISR Function we toggle the LED at PD6 & THEN AGAIN LOAD THE TCNT1 Register with the calcuated value.This is important as otherwise the TCNT1 will start counting from 0.
ISR (TIMER1_OVF_vect)
{
PORTD ^= (1<<6); // toggle LED
TCNT1 = 49910; // again load counter with calculated value
}
Complete code is here :
——————————
#include <avr/io.h>
#include <avr/interrupt.h>
int main (void)
{
DDRD |= (1<<6); // PD6 is Output
TCCR1B |= (1<<CS12); // prescaler 256 selected , clock is now 8000000/256= 31250Hz
TCNT1 = 49910; // load counter with calculated value
In previous above example we loaded the Counter with a calculated value & then waited for the counter to Overflow & used the Overflow interrupt to execute TIMER1_OVF_vect ISR
In compare mode, there is one compare register, where we can set value to compare with the Timer / counter register value. Once the compare value matches with timer / counter register value, compare match occurs. This compare match event can be used for waveform generation.
The Timer counts up until the value of the TCNT1 (Timer / counter register) register becomes equal to the content of OCRx (Compare register). As soon as TCNT1 becomes equal to the OCRx, compare match occurs and then timer will get cleared and OCFx flag will get set.
Hence, this comparison takes place inside the AVR CPU hardware . Once the counts value becomes equal to the compare value, a flag in the status register is set and the timer is reset automatically. Hence the name – CTC – Clear Timer on Compare
Let us explore the code :
First we enable the CTC mode by setting the bit WGM12 bit of TCCR1B.
Prescaler selected is 256 by setting CS12 bit in TCCR1B
TCCR1B |= (1 << WGM12) | (1 << CS12);
The WGM bits are found in both the registers.But we need to set only the WGM12 bit to enable CTC. This bit is found inside TCCR1B Register. So no need to set the TCCR1A register.
We then initialize the TCNT1 value to start from 0.
When the TCNT1 value reaches a compare value , an interrupt is enabled.
This compare value is loaded into a OCR1 x Register.
The Output Compare Register 1A – OCR1A and the Output Compare Register 1B – OCR1B are utilized for this purpose.
Since the compare value will be a 16-bit value (in between 0 and 65535), OCR1A and OCR1B are 16-bit registers. In ATMEGA16/32, there are two CTC channels – A and B. We can use any one of them or both. Let’s use OCR1A.
Let us load the Compare value as
OCR1A = 31250 ;
Calculation is as follows :
Clock is 8 MHz & we use a prescaler of 256
Now the clock to Timer1 is 8000000/256 = 31250 Hz
Time period is reciprocal of freq = 1/31250 = 0.000032 usec or 0.032 milli sec
To generate a delay of 500 ms 500ms/ 0.032 msec = 15625 counts
To generate 1 sec delay ( 1000millisec) 1000/0.032 = 31250
Now enable the OCIE1A Interrupt in TIMSK Register
TIMSK |= (1 << OCIE1A);
Whenever a match occurs (TCNT1 becomes equal to OCR1A ), an interrupt is fired (as OCIE1A is set) and the OCF1A flag is set (we do not check this flag manually, as we use interrupt).
Now we need an Interrupt Service Routine (ISR) to attend to the interrupt.
Executing the ISR clears the OCF1A flag bit automatically and the timer value (TCNT1) is reset.
The ISR is defined as follows with the correct vector name TIMER1_COMPA_vect
ISR (TIMER1_COMPA_vect)
{
PORTD ^= (1 << 6);
}
Complete code is as below :
———————————————-
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init()
{
TCCR1B |= (1 << WGM12) | (1 << CS12);
TCNT1 = 0;
OCR1A = 31250;
TIMSK |= (1 << OCIE1A);
sei();
}
ISR (TIMER1_COMPA_vect)
{
PORTD ^= (1 << 6);
}
int main(void)
{
DDRD |= (1 << 6);
timer1_init();
while(1) {}
}
———————————-
Compile & upload the HEX file to see the LED blinking at 1 sec interval
Hardware CTC Mode
Without Interrupt enable you can toggle or generate waveform on certain predefined OC pins which is called Hardware CTC , Output Compare
PB3, PD4, PD5 and PD7 represent the OUTPUT COMPARE pins
OC0 , OC1A, OC1B , OC2
These are the Output Compare pins of TIMER0, TIMER1 and TIMER2 respectively.
Timer/Counter1 Control Register A
The TCCR1A Register bits 4 to 7 decide the Compare output mode of unit A or B
These bits control the behaviour of the Output Compare (OC) pins. The behaviour changes depending upon the following modes:
· Non-PWM mode (normal / CTC mode)
· Fast PWM mode
· Phase Correct / Phase & Frequency Correct PWM mode
. CTC Mode
Simply set the timer1 to the mode 01 as seen in table above.
Whenever a compare match occurs, the OC1A pin is automatically toggled.
Only PD5 or PD4 (OC1A or OC1B) can be controlled this way, which means that we should connect the LED to PD5 (since we are using channel A
Timers/counters are an independent unit inside AVR. They run independently of what task CPU is performing. In this post we’ll explore the TIMER 0 Interrupts of AVR ATMEGA 16 .The previous post was on External Interrupts , this TIMER 0 is Internal Interrupt.
AVR ATMEGA 16 has 3 timers TIMER0 ,TIMER 1 & TIMER 2.Of these TIMER 1 is 16 bit Timer while others are 8 bit timers.
8-bit timer is capable of counting 2^8=256 steps from 0 to 255
Similarly a 16 bit timer is capable of counting 2^16=65536 steps from 0 to 65535. Due to this feature, timers are also known as counters. When the timer returns to its initial value of zero , We say that the timer/counter overflows.
Timer Events
OVERFLOW
In normal operation overflow occurs when the count value passes 0XFF & becomes 00
Timer 0 is a 8 bit timer. It basically means it can count from 0 to 2^8 255. The operation of timer 0 is straight forward. The TCNT0 register hold the timer Count and it is incremented on every timer “tick”. If the timer is turned on it ticks from 0 to 255 and overflows. If it does so, a Timer OverFlow Flag (TOV) is set.
The Flags are present inside the Register TIFR which is common for all 3 timers.
2. COMPARE MATCH
Another interesting feature is that a value can be set in the Output Compare Register (OCR0), and whenever TCNT0 reaches that value, the Output Compare Flag (OCF0) flag is Set.
We say Compare Match has occurred when the count value equals the contents of the output compare register
In this post we handle these above 2 events using the Interrupt concept.
OVERFLOW INTERRUPT
TCNT0 is the register that holds the current value of Timer
You can read from or write to this register to set your own time.
Timer0 works by incrementing this TCNT0a counter variable, also known as a counter register. The counter register can count to a value 0XFF , as Timer 0 is 8 bit .
The timer increments this counter one step at a time until it reaches its maximum value (255), at which point the counter overflows, and resets back to zero. The timer sets a flag (OVF0) bit .
You can check this flag inside TIFR register manually, or you can also have the timer trigger an interrupt (TOIE0) as soon as the flag is set. An Interrupt Service Routine (ISR) is called automatically to run code of your choice when the timer overflows.
The ISR will reset the overflow flag behind the scenes automatically
TIMER0 uses 2 8 bit DATA REGISTERS TCNT0 , OCR0
If you enable TCNT0 the register will increment from 0 counts upto 255 then overflos & start counting again ,
OCR0 never increments.You need to set a value bet 0 & 255
2 conditions occur OVERFLOW , COMPARE MATCH (TCNT0=OCR0)
The corresponding ISR vector name to be used in the ISR Function
ISR (TIMER0_OVF_vect) {} for Overflow interrupt
ISR (TIMER0_COMP_vect) {} for Compare Interrupt
Now let us Calculate the period of clock source .We use an external crystal oscillator of 8MHz
3. Set Timer OverFlow Interrupt TOIE0 bit of TIMSK register.
4. Enable global interrupt by sei () command.
5. Write code for ISR function with vector name TIMER0_OVF_vect
1. Code using OVERFLOW Interrupt that blinks LED at PD6 at 1 second interval
————————————————-
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t count;
int main (void)
{
DDRD |= (1<<6); //PD6 as output
TCNT0 = 0;
count = 0;
TCCR0 |= (1<<CS02) | (1<<CS00); // PRESCALER 1024
TIMSK = (1<<TOIE0);
sei();
while(1) {}
}
ISR (TIMER0_OVF_vect)
{
if (count == 31)
{
PORTD ^= (1<<6);
count=0;
}
else
count++;
}
—————————————–
To start with we include the 2 Header files & then declare a variable count.
volatile uint8_t count;
Here we use the keyword Volatile , as the variable is a Global one & will be used inside the ISR Function.If you do not use the volatile keyword & use the variable within ISR , the AVR-GCC compiler may report error while optimizing the code.
As we connect an LED at PD6 we make it as OUTPUT using left shift operator.
We then initialize the TCNT0 & the count variable to 0.
To set the prescaler as 1024 we need to set the bits CS00 & CS02 to 1inside the TCCR0 Register.
TCCR0 |= (1<<CS02) | (1<<CS00);
Next step is to enable the TIMER OVERFLOW INTERRUPT TOIE0 inside the
TIMSK Register
TIMSK = (1<<TOIE0);
Enable the Global interrupt using
sei();
which sets the I bit of SREG.
Next we’ve to write the code for ISR Function.
Correct Vector name must be used in this function.As we use the overflow interrupt select the correct vector name from the vector table TIMER0_OVF_vect
gfgf
ISR (TIMER0_OVF_vect)
{
if (count == 31)
{
PORTD ^= (1<<6);
count=0;
}
else
count++;
}
Let us see the calculation how we arrived at value 31 in the if condition.
The clock is external crystal 8MHz.We apply a prescaler of 1024.
Now the clock freq to counter becomes 8000000/1024 = 7812.5 Hz
Time period = 1/freq = 1/7812.5 = 0.000128usec or 0.128 milli sec
Overflow occurs every 256*0.000128 = 0.032768sec = 32.768 msec
To generate a time delay of 1 sec 1000/32.768 = 30.5 or 31
So the counter TCNT0 has to overflow 31 times to generate A TIME DELAY OF 1 SEC.
As done in previous example , save this file as main.c
Save the MFILE inside the same folder.You can use the same MFILE as of the previous post example.(Remember to save the C file as main.c)
Make ALL from WINAVR’s Programmers Notepad to create HEX file & then click Program to upload the file.Now the LED at PD6 blinksexactly at 1 second interval.
CTC mode operation:
Clear Timer on Compare Match It is better to use instead of Normal mode because in CTC mode, frequency can be easily adjusted.
When the Timer is triggered, register TCNT0 starts counting.
Timer0 has a OCR0 (Output Compare Register), which is continuously compared with TCNT0 register.
In CTC mode whenever match occurs, OCF0 (Output Compare Flag) will set to 1. If continuous wave form generation is required, OCF0 must be reset again.
Alternatively, if OCIE0 (Output Compare interrupt) and Global interrupt flags in SREG are set, OCF0 will reset automatically after interrupt execution.
The bits WGM0 [1:0] are programmed to select waveform generation mode. For enabling CTC set the bit WGM01
Programming steps:
1. Select CTC mode by programming WGM0 [1:0] bit.
2. Program Prescaler by setting CS bits of TCCR0.
3. Load Compare register OCR0 with a value between 0 & 255
4. Set compare Interrupt OCIE0 bit of TIMSK register.
5. Enable global interrupt by sei () command.
6. Write code for ISR function with vector name TIMER0_COMP_vect
OCF0 – Output Compare Flag 0 — Bit 1 of TIFR
is set whenever a compare match occurs. It is cleared automatically whenever the corresponding ISR is executed. Alternatively it is cleared by writing ‘1’ to it.
———————–
#include <avr/io.h>
#include <avr/interrupt.h>
void timer_init(void)
{
// set up timer with prescaler = 1024 and CTC mode
TCCR0 = (1 << WGM01) ;
TCCR0= (1 << CS00) | ( 1<<CS02);
// initialize counter
TCNT0 = 0;
// initialize compare value
OCR0 = 220;
// enable compare interrupt
TIMSK |= (1 << OCIE0);
// enable global interrupts
sei();
}
ISR (TIMER0_COMP_vect)
{
PORTD ^= (1 << 6);
}
int main(void)
{
DDRD |= (1 << 6);
timer_init();
while(1)
{
// do nothing
}
}
————————————–
TCCR0 = (1 << WGM01) ;
We enable the CTC mode in the TCCR0 Register by setting the bit WGM01
We then set the prescaler to 1024 by setting the bits CS00 & CS02
TCCR0= (1 << CS00) | ( 1<<CS02);
Initialize the TCNT0 Register with 0 value & then load the Output Compare Register with a value 220
OCR0 = 220;
As the TIMER0 is 8 bit timer we can only load the counter with a value between 0 & 255 .This will not create a longer delay & the LED will blink fast , almost stable.In the next post we’ll see the TIMER1 capable of generating longer delay as TIMER1 is 16 bit .
Next enable the Compare Interrupt OCIE0 within the TIMSK Register
TIMSK |= (1 << OCIE0);
Enable the Global interrupt using sei();
Inside the ISR function we just toggle the LED at PD6
ISR (TIMER0_COMP_vect)
{
PORTD ^= (1 << 6);
}
Note the usage of correct Vector name TIMER0_COMP_vect
Compile the code as done in previous examples & see the LED blinking very fast , as we could generate delay in millisec only using Compare mode.
HARDWARE INTERRUPT USING OC Pins
Instead of enabling the Interrupt we can make use of the OUTPUT COMPARE pins of AVR
The Output Compare Pins are seen as OC pins OC0 at PB3 for Timer0
Programming steps:
1. Select CTC mode by programming WGM0 [1:0] bit.
2. Program COM0 [1:0] bits and select “toggle OC0 if compare match”.
3. Set OC0 (PB3) pin as output pin.
4. Set OCIE0 bit of TIMSK register.
5. Enable global interrupt by “sei ()” command.
Mode WGM0[1:0] Mode
0 00 Normal
1 01 PWM,Phase Correct
2 10 CTC
3 11 Fast PWM
The Register TCCR0 also consists COM0 [1:0] bits. These bits are used to select functionality of OC0 pin. Following table shows function of COM 0[1:0]:
COM0[1:0] Description
00 Normal,OC0 disconnected
01 Toggle OC0 on compare match
10 Clear OC0 on compare match
11 Set OC0 on compare match
#include <avr/io.h>
#include <avr/interrupt.h>
void timer_init(void)
{
// set up timer with prescaler = 1024 and CTC mode
TCCR0 |= (1 << WGM01)|(1 << CS00)|(1 << CS02);
// set up timer OC0 pin (PB3) in toggle mode
TCCR0 |= (1 << COM00);
// initialize counter
TCNT0 = 0;
// initialize compare value
OCR0 = 220;
}
int main(void)
{
// connect led to pin PB3
DDRB |= (1 << 3);
// initialize timer
timer_init();
// loop forever
while(1) {}
}
OC0 is toggled automatically no need to keep track of any flag bits or ISR
Interrupts in AVR can be external (port pin sensing) or internal (Timers,ADC,UART,etc..)
When Interrupt occurs , the following things are done by AVR
1. AVR controller stops the current program execution and saves the context.
2. Control jumps to Interrupt Service Routine (ISR). (Each interrupt have an associated ISR which is a piece of code executed when an interrupt occurs.)
3. Execution of ISR is performed automatically..
4. When ISR is complete, the Controller resumes processing where it left off before the interrupt occurred.(main program resumes)
RESET is unmaskable interrupt & has the highest priority.
Other interrupt sources are Internal to AVR like -Timer , UART , ADC ,SPI , I2C ,etc..
This post is on the PORT PIN Interrupts i.e., EXTERNAL INTERRUPT
Let us connect an LED at PD0 & a switch at PD2.
PD2 is where Interrupt INT0 is sensed.
PD0 – LED
PD2 – SWITCH
Steps to configure the Interrupt:
————————————-
1. Set INT0 bit in the General Interrupt Control Register (GICR)
2. Configure MCU Control Register (MCUCR) to select interrupt type( let us configure for Falling edge).
3. Set Global Interrupt(I-bit) Enable bit in the AVR Status Register(SREG) sei()
4. Handle the interrupt in the Interrupt Service Routine code.
———————————-
General Interrupt Control Register (GICR)
In the GICR register enable the bit6 which configures INT0 Interrupt
It’s a good practice to mention the bit name itself in the code
GICR |= (1<<INT0) ;
Here we use the left shift operator to make the bit INT0 as 1
Type of INTERRUPT ( Rising Edge or Falling edge) is decided by setting bits 0 & 1of MCUCR Register
The MCUCR contains configuration bits which tells what signals will trigger INT0 and INT1
For this you need to set the ISC bits ( Interrupt Sense Control )
ISC00 & ISC01 configures the INT0 interrupt type.These are bits 0 & 1.
As seen in fig. above set this to Falling edge trigger by making ISC01 as 1.
MCUCR |= (1<< ISC01) ; (or you can also write MCUCR =0x02;)
Mentioning the bit name is always a good practice in coding
Now the Interrupt on INT0 is Falling edge-triggered (meaning that the interrupt is triggered when the signal changes from high to low)
We’ve connected a Reset type micro switch at PD2. When the switch is pressed 1 is applied to PD2 & when switch is released 0 is applied .Falling edge level triggering is from High to Low edge.
MCUCR is to configure INT0 & INT1 Interrupts.
INT2 is configured by another Register MCUCSR
INT2 can only be used as an edge-triggered interrupt.(no level trigger)
Now enable the Global Interrupt by setting the I-bit in SREG
It is the master control for all interrupts in AVR micro-controller.
This is done by calling sei();
When Interrupt occurs the ISR – Interrupt Service Routine is called automatically.Inside the ISR function we toggle the LED state.
ISR(INT0_vect)
{
PORTD ^= (1<<0);
}
The vector name used in this ISR is INT0_vect
Correct vector name to be used in the ISR function .Select it from the table below :
Once WINAVR is installed , you can see the Programmers Notepad & MFILE inside the WINAVR Folder.
Open Programmers Notepad to type in the C code.
To start with the code , include the 2 Header files on the top . avr/io.h defines all Port Registers & port pins of AVR IC & the util/delay.h is responsible for the Delay we use in the code.
#include <avr/io.h>
#include <util/delay.h>
Next we define the LCD Function definitions like
void LCD_send_command(unsigned char cmnd);
void LCD_send_data(unsigned char data);
void LCD_init(void);
Above all are user defined Functions & we’ve to write code for these functions.
For better code readability & reuse of coded we use # define statements
#define DATA_PORT PORTB
#define DATA_DDR DDRB
#define CNTRL_PORT PORTD
#define CNTRL_DDR DDRD
#define RS_PIN 4
#define RW_PIN 5
#define ENABLE_PIN 6
PORTB is defined as DATA_PORT & PORTD is defined as CNTRL_PORT , DDRB as DATA_DDR, DDRD as CNTRL_DDR
In the code , wherever DATA_PORT is mentioned it is replaced with PORTD & wherever CNTRL_PORT is mentioned is replaced with PORTD.
Also pins PD4 is defined as RS_PIN , PD5 as RW_PIN , PD6 as ENABLE_PIN .Its enough to mention only the pin number. Instead of PD5 you can mention only 5.
Later if you decide to change the port pins assigned to LCD , you need to change it in the #define statements and the rest of the code is left as it is.
First let us see the LCD_init() function which initializes the LCD
void LCD_init()
{
_delay_ms(10);
LCD_send_command(0x38);
LCD_send_command(0x0E);
LCD_send_command(0x01);
_delay_ms(10);
LCD_send_command(0x06);
}
To initialize the LCD we send the HEX values as command.The HEX command codes are
We send HEX value 0x38 to define 16 x 2 LCD 2lines & character size is 5 x 7
0x0E forDisplay ON & cursor blinking
0x06 to increment cursor
& 0x01 to Clear Screen
We send Command using Function LCD_sendcommand
Which accepts parameter as unsigned char
—————————————————–
void LCD_send_command(unsigned char cmnd)
{
DATA_PORT = cmnd;
CNTRL_PORT &= ~(1<< RW_PIN);
CNTRL_PORT &= ~(1<< RS_PIN);
CNTRL_PORT |= (1<< ENABLE_PIN);
_delay_us(2);
CNTRL_PORT &= ~(1<< ENABLE_PIN);
_delay_us(100);
}
————————————————–
Command received as unsigned char is assigned to DATA_PORT
RW pin is made LOW to enable Write operation
RS pin is made LOW to select COMMAND REGISTER
ENABLE pin is made HIGH & after a small delay made LOW ( pulse)
In the same way DATA is sent to LCD for Display using the following function :
——————————————–
void LCD_send_data(unsigned char data)
{
DATA_PORT = data;
CNTRL_PORT &= ~(1<< RW_PIN);
CNTRL_PORT |= (1<< RS_PIN);
CNTRL_PORT |= (1<< ENABLE_PIN);
_delay_us(2);
CNTRL_PORT &= ~(1<< ENABLE_PIN);
_delay_us(100);
}
—————————————
Data received as unsigned char is assigned to DATA_PORT
RW pin is made LOW to enable Write operation
RS pin is made HIGH to select DATA REGISTER
ENABLE pin is made HIGH & after a small delay made LOW ( pulse)
The next function takes 2 variables y & x & moves the cursor to that location on LCD
Following is the Function to print String characters on LCD
We put a string in memory location & use it as a Pointer
While String is greater than 0 , all the characters represented or pointed by the string variable is sent to LCD for printing
void LCD_print(char *string)
{
while(*string > 0)
{
LCD_send_data(*string++);
}
}
In the LCD_blink() function we send command , a hex value 0x08 to make the display OFF & after a delay we send a command Hex 0x 0C to ON the display, thus generating a blink effect
void LCD_blink()
{
LCD_send_command(0x08);
_delay_ms(250);
LCD_send_command(0x0C);
_delay_ms(250);
}
To clear the display we send command Hex 0x01 as seen in the LCD_clear function below
void LCD_clear(void)
{
LCD_send_command(0x01);
_delay_ms(100);
}
Finally in the main Function we declare PORTD as Output , as well as PORTC as OUTPUT.
This is done by assigning 0x FF to CNTRL_DDR ( PORTD) & DATA_DDR (PORTB)
Then we clear the LCD , Initialize it & go to first position & print the String
int main(void)
{
CNTRL_DDR = 0xFF;
CNTRL_PORT = 0x00;
DATA_DDR = 0xFF;
DATA_PORT = 0x00;
LCD_clear();
LCD_init();
LCD_goto(1,2);
LCD_print(“ALSELECTRO.COM”);
LCD_goto(2,3);
LCD_print(“16×2 LCD DEMO”);
Complete code for 8bit LCD MODE is as below :
—————————————————
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000UL // FCPU Definition for util/delay used in AVR STUDIO only
/*LCD function declarations */
void LCD_send_command(unsigned char cmnd);
void LCD_send_data(unsigned char data);
void LCD_init(void);
void LCD_goto(unsigned char y, unsigned char x);
void LCD_print(char *string);
void LCD_blink(void);
void LCD_clear(void);
#define DATA_PORT PORTB
#define DATA_DDR DDRB
#define CNTRL_PORT PORTD
#define CNTRL_DDR DDRD
#define RS_PIN 4
#define RW_PIN 5
#define ENABLE_PIN 6
int main(void)
{
CNTRL_DDR = 0xFF;
CNTRL_PORT = 0x00;
DATA_DDR = 0xFF;
DATA_PORT = 0x00;
LCD_clear();
LCD_init();
LCD_goto(1,2);
LCD_print(“ALSELECTRO.COM”);
LCD_goto(2,3);
LCD_print(“16×2 LCD DEMO”);
while(1)
{
}
}
/* This function sends a command ‘cmnd’ to the LCD module*/
void LCD_send_command(unsigned char cmnd)
{
DATA_PORT = cmnd;
CNTRL_PORT &= ~(1<< RW_PIN);
CNTRL_PORT &= ~(1<< RS_PIN);
CNTRL_PORT |= (1<< ENABLE_PIN);
_delay_us(2);
CNTRL_PORT &= ~(1<< ENABLE_PIN);
_delay_us(100);
}
/* This function sends the data ‘data’ to the LCD module*/
void LCD_send_data(unsigned char data)
{
DATA_PORT = data;
CNTRL_PORT &= ~(1<< RW_PIN);
CNTRL_PORT |= (1<< RS_PIN);
CNTRL_PORT |= (1<< ENABLE_PIN);
_delay_us(2);
CNTRL_PORT &= ~(1<< ENABLE_PIN);
_delay_us(100);
}
void LCD_init()
{
_delay_ms(10);
LCD_send_command(0x38);
LCD_send_command(0x0E);
LCD_send_command(0x01);
_delay_ms(10);
LCD_send_command(0x06);
}
/* This function moves the cursor the line y column x on the LCD module*/
This post is intended to assist you getting started with AVR DEVELOPMENT SELF LEARNING KIT.
It supports 40 pin AVR ICs like ATMEGA 16 /32 & a ZIF socket is provided to host the chip.All PORT pins are extended with berg pins for easy connections with peripherals.
For Analog input testing 2 nos variable pot are provided & for testing Digital inputs 4 nos switches are provided.A 4×4 keypad matrix is on board.
4 NOS 7 SEGMENT DISPLAY with driver circuit is provided.Other features include , EEPROM 24C16 , RTC DS1307, UART MAX232 , MOTOR DRIVER ULN2003. An LCD can be plugged with the port provided.
An ISP connector accepts USBASP programmer through a 10 pin FRC Header.
Download sample code ,WINAVR , USBASP DRIVER, AVRPAL.NET from HERE
Watch this video for details of installing USBASP driver & getting started with AVR Kit.
Connect the USBASP AVRDUDE with ISP connector & USB cable to your port on PC.Power up the kit with the 12v/1A adapter provided.Once the driver is installed , under Device manager USBASP appears
WINAVR is used to develop C code & upload HEX file on to the Target chip.WINAVR has a PROGRAMMERS NOTEPAD which is the IDE we use to develop code.
MFILE in WINAVR helps us to create the rules for making.This MAKE FILE must be saved within the same folder where you saved the C file.Compared to ATMEL STUDIO ( a HUGE Download) WINAVR is small & powerful.
To start with create an empty Folder , say LED ,inside your drive.Here is where we’ll be saving all our files.
Open PROGRAMMERS NOTEPAD & type in the following C code.
Save the file as LED.c inside the folder we created earlier.
Do not forget the .C Extension.
————————————————–
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0xFF; //Makes PORTC as Output
while(1) //infinite loop
{
PORTC = 0b00000001 ; // LED ON at PC0
_delay_ms(100); // delay
PORTC = 0b00000000 ; // LED OFF at PC0
_delay_ms(100); // delay
}
}
——————————————
The code starts with PREPROCESSOR Directives
# include <avr/io.h> defines all PORT names & pins of AVR
# include <util/delay.h> defines the delay timing
Then starts the MAIN function under which we first declare PORTC pis as all OUTPUT.
Notre that in AVR we use 1 to declare OUTPUT & a 0 to declare as INPUT (REVERSE TO PIC programming)
I/O Pins of AVR has 2 to 3 functions & each PORT is associated with 3 REGISTERS
For e.g PORTC is associated with 3 registers
DDRC —> DATA DIRECTION REGISTER Configures Port as INPUT (0) or OUTPUT (1)
PORTC —> Write Data to PORT Pins
PINC —> READ DATA from PORT Pins
Next is the indefinite loop while(1)
Inside which we make PORTC bit 0 as HIGH & all other pins LOW.
This is achieved by Binary notation
PORTC = 0b00000001 ;
After a delay
_delay_ms(100);
we make PORTC bit 0 as LOW
PORTC = 0b00000000 ;
Now we need to create the RULES for Making which is done through MFILE of WINAVR
Open MFILE.Click on MakeFile
Select MCUtYPE as ATmega16
Port as usb
Programmer as usbasp.
Under Progammer usbasp is not listed. Select any other type like STK500 & then click on Enable Editing.
Now you’re allowed to make changes.Type in usbasp against Programmer.
Scroll up to locate TARGET=main
Change this main to your C file name without any .c extension
Save the Makefile inside the same folder where your C code is stored.
Now click on MAKE ALL to generate HEX file.
Tools –> Program to load the HEX file automatically on to the target chip.
Now let us see how to use the BITWISE OPERATORS in C code
To improve code clarity & to leave generation of 1s & 0s to the compiler we use SHIFT OPERATORS.
For e.g instead of writing 0b0010 0000
we can write 0b0000 0001 <<5
or simply 1<<5 This is left shift operation.
0B0001 0000 << 3 will result 0B1000 0000 SHIFTING LEFT 3 TIMES
To generate 0B1110 1111 SHIFT FIRST & THEN INVERT IT
~(1<<5)
SETTING A BIT
To set an individual BIT we use the OR OPERATOR |
e.g DDRD = 0b0000 0001 To SET bit 4
SHIFT it 4 times to get 0b0001 0000
OR this result with DDRD Register
DDRD = DDRD | (0b00000001 <<4);
DDRD = DDRD | (1<<4);
or you can write simply DDRD |= (1<<4);
Only BIT 4 is SET & other bits not affected.
You can also define a constant & use it
# define LED 4
DDRD |= (1<<LED);
CLEAR A BIT
e.g DDRD = 0b0101 0101;
To clear the bit 2 (shown in bold letter above)
start with binary no. 0b0000 0001
Left SHIT 2 TIMES to get 0b0000 0100
Invert this to get 0b1111 1011
use the & OPERATOR with DDRD Register
#define switch 2
DDRD &= ~ (1<< SWITCH);
CHECKING A BIT WHETHER 1 OR 0
To check status of 4th bit of PIND Register
Notice the use of PIN Register here
#define switch 4
status = (PIND & (1<< SWITCH) !=0);
TOGGLING A BIT
To toggle 4th bit of PORT D
PORTD = 0B0000 0000
START with 0b0000 0001 shift by 4 times to get
0b0001 000
X OR with PORTD
#define LED 4
PORTD ^= (1<< LED);
Every time this statement is executed the LED changes state
Following is the code with BITWISE operators implemented.
We use OR EQUAL LEFT SHIFT to declare portC as output
Inside while loop PORTC BIT 0 is made ON & then OFF after a delay , which is repeated for ever.
———————————————–
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC |= (1 << PC0); //Makes PORTC PC0 Pin22 as Output
while(1) //infinite loop
{
PORTC |= (1 << PC0); //Turns ON LED at PC0 or PORTC=0b00000001
_delay_ms(100); // delay
PORTC &= ~(1 << PC0); //Turns OFF LED or PORTC=0b00000000
_delay_ms(100); // delay
}
}
First time in India , VEGA ROBOKITS has engineered a development board universal to both AVR & 8051 ICs.The board has in built Programmer capable of programming both AVR & 8051 family ICs.
A 40 pin ZIF socket is used as Target to hold the 8051 IC. Additional 40 pin ZIF socket with modified connection is provided to host AVR ICs.This additional ZIF socket should be placed over the on- board ZIF socket to use AVR ICs.
8051 PROGRAMMER & DEVELOPMENT
To start with we shall see how to use this board for 8051 development.
Select switch 1 to USB position ,if you connect the board to PC using A to B USB cable.Now the power is taken from USB itself. If this switch is selected to other side , the board needs an external 12v/1A adapter.
Select the ISP switch (switch 2 near the middle of board) to ON position.This makes sure that you’re going to program the chip .
Put the jumper (found on top of I2C EEPROM IC) on 8051 position.
WILPRO’s WLAR software is used as an application to fuse the HEX files.Download the zip file from :
Unzip the driver file & double click on “PL2303_Prolific_DriverInstaller_v1.10.0 “ EXE file to install the drivers.
Connect the USB cable of board to PC & open the DEVICE MANAGER.
If the PORT allotted is within range 1 to 9 , you can start the WLPRO application and proceed to load HEX file.
If the port allotted is a double digit , then WLPRO will enter DEMO mode .Only in ON LINE Mode you can load the HEX file.
To solve this , RIGHT CLICK on the port allotted inside Device Manager & select PROPERTIES.
Under PROPERTIES window select PORT SETTINGS
Click on ADVANCED button under PORT SETTINGS.
From the DROP DOWN you can select a PORT number between 1 & 9 & click OK.
If the port number is not free , you can try overwriting the pre allotted port number & confirm.
After PORT setting to single digit , open the WILLAR software . Now you can see ONLINE MODE at the bottom of screen.
Click on DEVICE button & select the target device asAT89S51@ISP
If you select plain AT89S51 , DEVICE ID ERROR will be returned while programming .So make sure to select the ISP version as device.
Click on LOAD button & browse to the location of the HEX file to be fused.Select the HEX file & then click OPEN.
On the next LOAD FILE window leave the File type as “INTEL HEX” & CLICK ok.
You’ll see LOAD FILE SUCCESSFUL display.
Now click on the PROGRAM button on the left pane.
Programming is DONE & you get Program Successful display.
If you click the AUTO mode button , all functions like Erase,Blank check ,Program,Verify & code copy Protect will be done automatically one by one.
To test the program loaded , change the switch 2 to ISP OFF position .Push RESET button to see the result of blinking LED .
AVR PROGRAMMER &DEVELOPMENT
Select USB ON (switch 1)
Select the ISP (switch2) to ON position.
Put the Jumper on top of I2C chip to AVR position.
Place the converter socket on the ZIF socket & lock it.Make sure that the handles of sockets match.Do not place the socket in REVERSE as it may damage the target IC.
Nowadays Laptops come preloaded with Windows 8 OS. For our Embedded software installation it is not possible to install Drivers , as WIN8 has added security against unsigned drivers.
For Windows 8 to accept drivers , we’ve to disable the security measure of testing unsigned drivers.
Particularly while trying to install AVR USB drivers ,this security measure won’t allow you to install the drivers.
Follow the steps explained below to over ride this problem.
Under Charms bar click on the Gear icon “Settings”
On next screen click on “Change PC Settings”
On PC Settings screen under General scroll down to bottom to select “Restart Now “under Advanced StartUp
Click On Trouble shoot option
Click On Advanced Options under Troubleshoot screen
Select StartUp Settings
Click Restart
A list of Start Up Settings appear. Press number 7 on your key board to Disable Driver Signature Enforcement.
Now your PC reboots with driver signature enforcement disabled.
Once you did this you will be able to install unsigned drivers.
Now connect your USBasp programmer to the USB port of your laptop. Ignore the message that ‘Device driver software was not successfully installed’.
Go to Device Manager in control Panel and you will find ‘USBasp’ with yellow mark. Click on it and select ‘Update Driver Software.’
select ‘Browse my computer for driver software’. After this browse to the location where you have extracted the USBasp drivers
Click next and ignore the security warning ‘Windows can’t verify the publisher of this driver software’ and select ‘Install this driver software anyway’
Now the drivers are successfully installed & you’ll see this :