Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C Programming for microcontrollers (Joe Pardue, 2005).pdf
Скачиваний:
277
Добавлен:
12.08.2013
Размер:
4.55 Mб
Скачать

Chapter 6: C Functions and Program Structures

Save this file as Demonstrator.c.

PC_Comm

The next two programs, PC_Comm.h and PC_Comm.c can be copied from the CD to the CommDemo directory, or if you want a preview of coming attractions, you can open a new C/C++ file in Programmer’s Notepad and write:

// PC_Comm.h #include <avr/io.h>

#include <avr/interrupt.h> #include <avr/delay.h>

#include <stdlib.h>

#include "Demonstrator.h"

void OSCCAL_calibration(void) ; void USARTinit(void);

char isCharAvailable(void); char receiveChar(void); void sendChar(char ) ;

void sendString(char *);

Save this file as PC_Comm.h.

In Programmer’s Notepad open a new C/C++ file and write:

// PC_Comm.c

#include "PC_Comm.h"

int main(void)

{

char string[64]; unsigned char count = 0;

// run the initialization routine initializer();

//Begin forever chatting with the PC for(;;)

{

// Check to see if a character is waiting if( isCharAvailable() == 1 )

{

//If a new character is received, get it string[count++] = receiveChar();

//receive a packet up to 64 bytes long

102

Chapter 6: C Functions and Program Structures

if(string[count-1] == '\n')// HyperTerminal string ends with \r\n

{

string[count-2] = '\0'; //convert to a string parseInput(string);

string[0] = '\0'; count = 0;

}

else if(count > 64)

{

count = 0; string[0] = '\0';

sendString("Error - received > 64 characters");

}

}

}

return 0;

}

char isCharAvailable()

{

//Does the RX0 bit of the USART Status and Control Register

//indicate a char has been received?

if ( (UCSR0A & (0x80)) ) return 1; else return 0;

}

char receiveChar()

{

// Return the char in the UDR0 register return UDR0;

}

void sendChar(char data)

{

int i = 0;

//To send data with the USART put the data in the USART data register UDR0 = data;

//Check to see if the global interrupts are enabled

if(SREG & 0x80)

{

// Wait until the byte is sent or we count out while ( !(UCSR0A&0x40) && (i<10000) )

{

i++;

}

}

else // Wait until the byte is sent while( !(UCSR0A&0x40) );

// Clear the TXCflag UCSR0A=UCSR0A|0x40;

}

103

Chapter 6: C Functions and Program Structures

void sendString(char s[])

{

int i = 0;

while(i < 64) // don't get stuck if it is a bad string

{

if( s[i] == '\0' ) break; // quit on string terminator sendChar(s[i++]);

}

}

void USARTinit()

{

// Increase the oscillator to 2 Mhz for the 19200 baudrate: CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable

//set prescaler = 4, Inter RC 8Mhz / 4 = 2Mhz CLKPR = (1<<CLKPS1);

//Set the USART baudrate registers for 19200 UBRR0H = 0;//(unsigned char)(baudrate>>8); UBRR0L = 12;//(unsigned char)baudrate;

//Enable 2x speed change

UCSR0A = (1<<U2X0);

// Enable receiver and transmitter

UCSR0B

=

(1<<RXEN0)|(1<<TXEN0)|(0<<RXCIE0)|(0<<UDRIE0);

// Set

the USART to asynchronous at 8 bits no parity and 1 stop bit

UCSR0C

=

(0<<UMSEL0)|(0<<UPM00)|(0<<USBS0)|(3<<UCSZ00)|(0<<UCPOL0);

}

 

 

 

//Calibrate the internal OSCCAL byte, using the external

//32,768 kHz

crystal as reference

void OSCCAL_calibration(void)

{

 

char calibrate = 0;//FALSE;

unsigned

int temp;

char tempL;

 

unsigned

 

CLKPR = (1<<CLKPCE);

// set Clock Prescaler Change Enable

// set

prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz

CLKPR = (1<<CLKPS1) | (1<<CLKPS0);

TIMSK2

=

0;

//disable OCIE2A and TOIE2

ASSR =

(1<<AS2);

//select asynchronous operation of timer2 (32,768kHz)

OCR2A = 200;

// set timer2 compare value

TIMSK0

=

0;

// delete any interrupt sources

TCCR1B

=

(1<<CS10);

// start timer1 with no prescaling

TCCR2A

=

(1<<CS20);

// start timer2 with no prescaling

//wait

for TCN2UB and TCR2UB to be cleared

104

Chapter 6: C Functions and Program Structures

while((ASSR & 0x01) | (ASSR & 0x04));

// wait for external crystal to stabilise for(int i = 0; i < 10; i++)

_delay_loop_2(30000);

while(!calibrate)

{

cli(); // mt __disable_interrupt(); // disable global interrupt

TIFR1 = 0xFF;

// delete TIFR1

flags

TIFR2 = 0xFF;

// delete TIFR2

flags

TCNT1H = 0;

// clear timer1

counter

TCNT1L = 0;

// clear timer2

counter

TCNT2 = 0;

while ( !(TIFR2 && (1<<OCF2A)) );

// wait for timer2 compareflag

TCCR1B = 0; // stop timer1

sei(); // __enable_interrupt(); // enable global interrupt

if ( (TIFR1 && (1<<TOV1)) )

{

temp = 0xFFFF;

// if timer1 overflows, set the temp to 0xFFFF

}

else

{// read out the timer1 counter value tempL = TCNT1L;

temp = TCNT1H;

temp = (temp << 8);

temp += tempL;

}

if (temp > 6250)

{

OSCCAL--; // the internRC oscillator runs to fast, decrease the OSCCAL

}

else if (temp < 6120)

{

OSCCAL++; // the internRC oscillator runs to slow, increase the OSCCAL

}

else

calibrate = 1;//TRUE;

// the interRC is correct

TCCR1B = (1<<CS10); // start timer1

}

}

Save this file as PC_Comm.c.

Finally make these changes to the makefile:

105