|
发表于 2007-5-21 23:49:29
|
显示全部楼层
在这个电路是完全可以构成<<脱离PC的AVR芯片恢复器>>只增加1个按键、2支电阻、1只LED。
在TXD_PIN连接1支电阻1K再连接1个按键、按键另1端接地。
这按键有2个功能:
1. 在开机时按下按键,M8将进入bootloader状态,软件进行升级。
2. 在开机时没有按下按键时,进入正常PC上位机控制,在没有接收到(PC_TXD=HIGH=<M8_RXD>)
信号,按下按键时执行脱离PC<<专用的AVR芯片恢复器>>工作程序。
在BS2_PIN连接1支电阻1只LED作为状态显示灯。
这电路再作合理的修改,可构成全功能的编程器,可编程AVR全系列的单片机<低压串行ISP编程、
高压串行ISP编程、高压并行编程>及对PIC的单片机讲行编程。
先增加1个由M8输出PWM可控制的升压电路(12V-14V),ADC其中1PIN作输入取样电压到M8作运算后
再控制PWM的升压电路在所需要的电压。可参孝以下电路。
RESET脚要设置为IO及选用内部RC 8MHz振荡,将RC 8MHz振荡设置成7372800MHz,OSCCAL=0x80-0xA0。
提供-个精简全功能的STK500v2 compatible bootloader程序才900多byte,现在我的M8是选用内部RC 8MHz振荡设置成7372800MHz,
OSCCAL=0x90。
/*****************************************************************************
Title: STK500v2 compatible bootloader
*****************************************************************************/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/boot.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <util/delay.h>
#include "command.h"
// Uncomment the following lines to save code space
//#define REMOVE_PROGRAM_LOCK_BIT_SUPPORT // disable program lock bits
//#define REMOVE_BOOTLOADER_LED // no LED to show active bootloader
//#define REMOVE_PROG_PIN_PULLUP // disable internal pullup, use external
// Pin "PROG_PIN" on port "PROG_PORT" has to be pulled low
// (active low) to start the bootloader
// uncomment #define REMOVE_PROG_PIN_PULLUP if using an external pullup
#define PROG_PORT PORTD
#define PROG_DDR DDRD
#define PROG_IN PIND
#define PROG_PIN PIND1
/*
* Active-low LED on pin "PROGLED_PIN" on port "PROGLED_PORT"
* indicates that bootloader is active
*/
#define PROGLED_PORT PORTB
#define PROGLED_DDR DDRB
#define PROGLED_PIN PINB1
// define CPU frequency in Mhz here if not defined in Makefile
// UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
#define BAUDRATE 115200
// Enable (1) or disable (0) USART double speed operation
#define UART_BAUDRATE_DOUBLE_SPEED 0
/*
* HW and SW version, reported to AVRISP, must match version of AVRStudio
*/
#define CONFIG_PARAM_BUILD_NUMBER_LOW 0
#define CONFIG_PARAM_BUILD_NUMBER_HIGH 1
#define CONFIG_PARAM_HW_VER 0x0F
#define CONFIG_PARAM_SW_MAJOR 2
#define CONFIG_PARAM_SW_MINOR 0x0A
#define CONFIG_PARAM_OSC_CMATCH 1
/*
* Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
* (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
*/
#define BOOTSIZE 512
#define APP_END (FLASHEND -(2*BOOTSIZE) + 1)
/*
* Signature bytes are not available in avr-gcc io_xxx.h
*/
#if defined (__AVR_ATmega8__)
#define SIGNATURE_BYTES 0x1E9307
#elif defined (__AVR_ATmega16__)
#define SIGNATURE_BYTES 0x1E9403
#elif defined (__AVR_ATmega32__)
#define SIGNATURE_BYTES 0x1E9502
#elif defined (__AVR_ATmega8515__)
#define SIGNATURE_BYTES 0x1E9306
#elif defined (__AVR_ATmega8535__)
#define SIGNATURE_BYTES 0x1E9308
#elif defined (__AVR_ATmega88__)
#define SIGNATURE_BYTES 0x1E930A
#elif defined (__AVR_ATmega162__)
#define SIGNATURE_BYTES 0x1E9404
#elif defined (__AVR_ATmega168__)
#define SIGNATURE_BYTES 0x1E9406
#elif defined (__AVR_ATmega128__)
#define SIGNATURE_BYTES 0x1E9702
#else
#error "no signature definition for MCU available"
#endif
/*
* Defines for the various USART registers
*/
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
/* ATMega8 with one USART */
#define UART_BAUD_RATE_LOW UBRRL
#define UART_STATUS_REG UCSRA
#define UART_CONTROL_REG UCSRB
#define UART_ENABLE_TRANSMITTER TXEN
#define UART_ENABLE_RECEIVER RXEN
#define UART_TRANSMIT_COMPLETE TXC
#define UART_RECEIVE_COMPLETE RXC
#define UART_DATA_REG UDR
#define UART_DOUBLE_SPEED U2X
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
/* ATMega with two USART */
#define UART_BAUD_RATE_LOW UBRR0L
#define UART_STATUS_REG UCSR0A
#define UART_CONTROL_REG UCSR0B
#define UART_ENABLE_TRANSMITTER TXEN0
#define UART_ENABLE_RECEIVER RXEN0
#define UART_TRANSMIT_COMPLETE TXC0
#define UART_RECEIVE_COMPLETE RXC0
#define UART_DATA_REG UDR0
#define UART_DOUBLE_SPEED U2X0
#else
#error "no UART definition for MCU available"
#endif
// Macros to map the new ATmega88/168 EEPROM bits
#ifdef EEMPE
#define EEMWE EEMPE
#define EEWE EEPE
#endif
/*
* Macro to calculate UBBR from XTAL and baudrate
*/
#if UART_BAUDRATE_DOUBLE_SPEED
#if defined(__AVR_ATmega8__)
// 选用MEGA8内部RC 8MHZ振荡
#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5) //-1.0+0.5
#elif defined (__AVR_ATmega16__)
// 选用MEGA16内部RC 8MHZ振荡
#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1) //-1.0+0.5
#endif
#else
#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1) //-1.0+0.5
#endif
/*
* use 16bit address variable for ATmegas with <= 64K flash
*/
#if defined(RAMPZ)
typedef uint32_t address_t;
#else
typedef uint16_t address_t;
#endif
// function prototypes
static void sendchar(char C);
static unsigned char recchar(void);
/*
* since this bootloader is not linked against the avr-gcc crt1 functions,
* to reduce the code size, we need to provide our own initialization
*/
void __jumpMain (void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
void __jumpMain(void)
{
#ifndef REMOVE_PROG_PIN_PULLUP
PROG_PORT |= (1<<PROG_PIN); // Enable internal pullup
#endif
SP=0X45F; // RAMEND
// asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
asm volatile ( "clr __zero_reg__" ); // GCC depends on register r1 set to 0
asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) ); // set SREG to 0
asm volatile ( "rjmp main"); // jump to main()
}
// send single byte to USART, wait until transmission is completed
static void sendchar(char c)
{
UART_DATA_REG = c; // prepare transmission
while (!(UART_STATUS_REG & (1 << UART_TRANSMIT_COMPLETE)));// wait until byte sent
UART_STATUS_REG |= (1 << UART_TRANSMIT_COMPLETE); // delete TXCflag
}
// Read single byte from USART, block if no data available
static unsigned char recchar(void)
{
while(!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE))); // wait for data
return UART_DATA_REG;
}
int main(void)
{
address_t address,eraseAddress;
//unsigned char msgParseState;
unsigned int i,msgLength;
unsigned char c, *p,seqNum,checksum;
unsigned char msgBuffer[285];
//Branch to bootloader or application code ?
if(PROG_IN & (1<<PROG_PIN))
{
#ifndef REMOVE_BOOTLOADER_LED
// PROG_PIN pulled low, indicate with LED that bootloader is active
PROGLED_DDR |= (1<<PROGLED_PIN);
PROGLED_PORT &= ~(1<<PROGLED_PIN);
#endif
#if SELECT_HARDWARE_UART
// Init UART
// set baudrate and enable USART receiver and transmiter without interrupts
#if UART_BAUDRATE_DOUBLE_SPEED
UART_STATUS_REG |= (1 <<UART_DOUBLE_SPEED);
#endif
// 选用MEGA8内部RC 8MHZ振荡
OSCCAL=0X90; //0xAD;
// Init UART
UART_BAUD_RATE_LOW = UART_BAUD_SELECT(BAUDRATE,F_CPU);
UART_CONTROL_REG = (1 << UART_ENABLE_RECEIVER) | (1 << UART_ENABLE_TRANSMITTER);
#else
#if defined (__AVR_ATmega8__)
// 选用MEGA8内部RC 8MHZ振荡
OSCCAL=0x90; //0x96;
#elif defined (__AVR_ATmega16__)
// 选用MEGA16内部RC 8MHZ振荡
OSCCAL=0xB7;
#endif
PORTD |= 0B00000011;
DDRD |= 0B00000010;
#endif
// main loop
while(1)
{
msg_MESSAGE_START:
c = recchar();
if ( c != MESSAGE_START ){
goto msg_MESSAGE_START;
}
checksum = MESSAGE_START^0;
seqNum = recchar();
checksum ^= seqNum;
c = recchar();
checksum ^= c;
msgLength = c << 8;
c = recchar();
checksum ^= c;
msgLength |= c;
c = recchar(); //TOKEN
checksum ^= c;
for(i=0;i< msgLength;i++)
{
c = recchar();
checksum ^= c;
msgBuffer = c;
}
if( recchar() != checksum ){
goto msg_MESSAGE_START;
}
//Now process the STK500 commands, see Atmel Appnote AVR068
if(msgBuffer[0]==CMD_SIGN_ON)
{
msgBuffer[1] = STATUS_CMD_OK;
msgBuffer[2] = 8;
msgBuffer[3] = 'A';
msgBuffer[4] = 'V';
msgBuffer[5] = 'R';
msgBuffer[6] = 'I';
msgBuffer[7] = 'S';
msgBuffer[8] = 'P';
msgBuffer[9] = '_';
msgBuffer[10] = '2';
msgLength = 11;
}
else if(msgBuffer[0]==CMD_GET_PARAMETER)
{
unsigned char value;
switch(msgBuffer[1])
{
case PARAM_BUILD_NUMBER_LOW:
value = CONFIG_PARAM_BUILD_NUMBER_LOW;
break;
case PARAM_BUILD_NUMBER_HIGH:
value = CONFIG_PARAM_BUILD_NUMBER_HIGH;
break;
case PARAM_HW_VER:
value = CONFIG_PARAM_HW_VER;
break;
case PARAM_SW_MAJOR:
value = CONFIG_PARAM_SW_MAJOR;
break;
case PARAM_SW_MINOR:
value = CONFIG_PARAM_SW_MINOR;
break;
case PARAM_OSC_PSCALE:
value = CONFIG_PARAM_OSC_CMATCH;
break;
default:
value = 0;
break;
}
msgLength = 3;
msgBuffer[1] = STATUS_CMD_OK;
msgBuffer[2] = value;
}
else if( (msgBuffer[0]==CMD_SET_PARAMETER)\
||(msgBuffer[0]== CMD_ENTER_PROGMODE_ISP)\
||(msgBuffer[0]==CMD_LEAVE_PROGMODE_ISP) )
{
msgLength = 2;
msgBuffer[1] = STATUS_CMD_OK;
}
else if(msgBuffer[0]==CMD_READ_SIGNATURE_ISP)
{
unsigned char signatureIndex = msgBuffer[4];
unsigned char signature;
if ( signatureIndex == 0 )
signature = (SIGNATURE_BYTES >>16) & 0x000000FF;
else if ( signatureIndex == 1 )
signature = (SIGNATURE_BYTES >> 8) & 0x000000FF;
else
signature = SIGNATURE_BYTES & 0x000000FF;
msgLength = 4;
msgBuffer[1] = STATUS_CMD_OK;
msgBuffer[2] = signature;
msgBuffer[3] = STATUS_CMD_OK;
}
else if( (msgBuffer[0]==CMD_READ_OSCCAL_ISP)\
||(msgBuffer[0]==CMD_READ_LOCK_ISP) )
{
msgLength = 4;
msgBuffer[1] = STATUS_CMD_OK;
if(msgBuffer[0]==CMD_READ_LOCK_ISP)
msgBuffer[2] = boot_lock_fuse_bits_get( GET_LOCK_BITS );
else
msgBuffer[2] = OSCCAL;
msgBuffer[3] = STATUS_CMD_OK;
}
else if(msgBuffer[0]==CMD_READ_FUSE_ISP)
{
unsigned char fuseBits;
if ( msgBuffer[2] == 0x50 )
{
if ( msgBuffer[3] == 0x08 )
fuseBits = boot_lock_fuse_bits_get( GET_EXTENDED_FUSE_BITS );
else
fuseBits = boot_lock_fuse_bits_get( GET_LOW_FUSE_BITS );
}
else
{
fuseBits = boot_lock_fuse_bits_get( GET_HIGH_FUSE_BITS );
}
msgLength = 4;
msgBuffer[1] = STATUS_CMD_OK;
msgBuffer[2] = fuseBits;
msgBuffer[3] = STATUS_CMD_OK;
}
#ifndef REMOVE_PROGRAM_LOCK_BIT_SUPPORT
else if(msgBuffer[0]==CMD_PROGRAM_LOCK_ISP)
{
unsigned char lockBits = msgBuffer[4];
lockBits = (~lockBits) & 0x3C; // mask BLBxx bits
boot_lock_bits_set(lockBits); // and program it
boot_spm_busy_wait();
msgLength = 3;
msgBuffer[1] = STATUS_CMD_OK;
msgBuffer[2] = STATUS_CMD_OK;
}
#endif
else if(msgBuffer[0]==CMD_CHIP_ERASE_ISP)
{
eraseAddress = 0;
msgLength = 2;
msgBuffer[1] = STATUS_CMD_OK;
}
else if(msgBuffer[0]==CMD_LOAD_ADDRESS)
{
#if defined(RAMPZ)
address = ( ((address_t)(msgBuffer[1])<<24)|((address_t)(msgBuffer[2])<<16)|((address_t)(msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;
#else
address = ( ((msgBuffer[3])<<8)|(msgBuffer[4]) )<<1; //convert word to byte address
#endif
msgLength = 2;
msgBuffer[1] = STATUS_CMD_OK;
}
else if( (msgBuffer[0]==CMD_PROGRAM_FLASH_ISP)\
||(msgBuffer[0]==CMD_PROGRAM_EEPROM_ISP) )
{
unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2];
unsigned char *p = msgBuffer+10;
unsigned int data;
unsigned char highByte, lowByte;
address_t tempaddress = address;
if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP )
{
// erase only main section (bootloader protection)
if ( eraseAddress < APP_END )
{
boot_page_erase(eraseAddress); // Perform page erase
boot_spm_busy_wait(); // Wait until the memory is erased.
eraseAddress += SPM_PAGESIZE; // point to next page to be erase
}
/* Write FLASH */
do {
lowByte = *p++;
highByte = *p++;
data = (highByte << 8) | lowByte;
boot_page_fill(address,data);
address = address + 2; // Select next word in memory
size -= 2; // Reduce number of bytes to write by two
} while(size); // Loop until all bytes written
boot_page_write(tempaddress);
boot_spm_busy_wait();
boot_rww_enable(); // Re-enable the RWW section
}
else
{
/* write EEPROM */
do {
EEARL = address; // Setup EEPROM address
EEARH = (address >> 8);
address++; // Select next EEPROM byte
EEDR= *p++; // get byte from buffer
EECR |= (1<<EEMWE); // Write data into EEPROM
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)); // Wait for write operation to finish
size--; // Decrease number of bytes to write
} while(size); // Loop until all bytes written
}
msgLength = 2;
msgBuffer[1] = STATUS_CMD_OK;
}
else if( (msgBuffer[0]==CMD_READ_FLASH_ISP)\
||(msgBuffer[0]==CMD_READ_EEPROM_ISP) )
{
unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2];
unsigned char *p = msgBuffer+1;
msgLength = size+3;
*p++ = STATUS_CMD_OK;
if (msgBuffer[0] == CMD_READ_FLASH_ISP )
{
unsigned int data;
// Read FLASH
do {
#if defined(RAMPZ)
data = pgm_read_word_far(address);
#else
data = pgm_read_word_near(address);
#endif
*p++ = (unsigned char)data; //LSB
*p++ = (unsigned char)(data >> 8); //MSB
address += 2; // Select next word in memory
size -= 2;
}while (size);
}
else
{
/* Read EEPROM */
do {
EEARL = address; // Setup EEPROM address
EEARH = ((address >> 8));
address++; // Select next EEPROM byte
EECR |= (1<<EERE); // Read EEPROM
*p++ = EEDR; // Send EEPROM data
size--;
}while(size);
}
*p++ = STATUS_CMD_OK;
}
else
{
msgLength = 2;
msgBuffer[1] = STATUS_CMD_FAILED;
}
/*
* Now send answer message back
*/
sendchar(MESSAGE_START);
checksum = MESSAGE_START^0;
sendchar(seqNum);
checksum ^= seqNum;
c = ((msgLength>>8)&0xFF);
sendchar(c);
checksum ^= c;
c = msgLength & 0x00FF;
sendchar(c);
checksum ^= c;
sendchar(TOKEN);
checksum ^= TOKEN;
p = msgBuffer;
while ( msgLength )
{
c = *p++;
sendchar(c);
checksum ^=c;
msgLength--;
}
sendchar(checksum);
seqNum++;
}//for
#ifndef REMOVE_BOOTLOADER_LED
PROGLED_DDR &= ~(1<<PROGLED_PIN); // set to default
#endif
}
/*
* Now leave bootloader
*/
#ifndef REMOVE_PROG_PIN_PULLUP
PROG_PORT &= ~(1<<PROG_PIN); // set to default
#endif
// boot_rww_enable(); // enable application section
// (*((void(*)(void))PROG_START))();
asm volatile ( "push r1" "
\t" // Jump to Reset vector in Application Section
"push r1" "
\t"
"ret" "
\t"
::);
/*
* Never return to stop GCC to generate exit return code
* Actually we will never reach this point, but the compiler doesn't
* understand this
*/
for(;;);
}
-----此内容被andy于2007-05-21,23:25:48编辑过 |
|