⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 用AVR单片机做的一些程序,包括跑马灯显示,PWM产生,ADC转换等
💻 C
字号:
/*
实验十九:
	mega128 BOOT实验。
	1、AVR单片机IAP实验,使用AVRISP协议及上位机软件,进行IAP升级实验。
		进入IAP方法:在启动时按住S7键。
		退出IAP方法:在不按S7按键的情况下复位CPU即可。
		使用方法:和正常的AVRISP下载方式相同。
	2、外部3.6864 M晶振。
	3、进行此实验请插上LED短路块,与PC机的通信由UART0完成。
	4、这个实验是一个高难度实验,同样也是一个很有意义的实验,
		此实验可以移植到产品里面使用。

	AVR  mega128学习板
	www.iccavr.com 阿发
	5:18 2007-10-20

	本实验代码主要参考了小松工程和马潮老师的作品。
*/

#include "init.h"

/*主函数*/
void main(void) {

	unsigned char rec_data;
	static unsigned int msgCounter;
	init();	
	while (1) {
		rec_data=getChar();
		if (statusMachine == ST_START) {
		 	//flag = 1;
			//TCCR1B = 0x00;
			if (rec_data==MESSAGE_START) {					/*同步*/
				statusMachine = ST_GET_SEQ_NUM;	
				checkSum = MESSAGE_START;
				}
			}
		else if (statusMachine == ST_GET_SEQ_NUM) {			/*序号*/
			seqNumber = rec_data;
			checkSum ^= rec_data; 
			statusMachine = ST_MSG_SIZE_1;
			}
		else if (statusMachine == ST_MSG_SIZE_1) {			/*长度*/
			msgSize = rec_data;
			msgSize <<=8;
			checkSum ^= rec_data;
			statusMachine = ST_MSG_SIZE_2;
			}
		else if (statusMachine == ST_MSG_SIZE_2) {			/*长度*/
			msgSize |= rec_data;
			checkSum ^= rec_data;
			statusMachine = ST_GET_TOKEN;
			}
		else if (statusMachine == ST_GET_TOKEN) {			/*关键字*/
			if (rec_data==TOKEN) {
				checkSum ^= rec_data;
				statusMachine = ST_GET_DATA;
				msgCounter=0;
				}
			else {
				statusMachine = ST_START;
				}
			}
		else if (statusMachine == ST_GET_DATA) {			/*读取数据*/
			msg_buffer[msgCounter++]=rec_data;
			checkSum ^= rec_data;
			if (msgCounter==msgSize) {						/*判断是否完成*/
				statusMachine = ST_GET_CHECK;
				}
			}
		else if (statusMachine == ST_GET_CHECK) {			/*数据校验*/
			if (rec_data == checkSum) {
				packageProcess(seqNumber);
				}		
			statusMachine = ST_START;
			}
		}
}

/*数据包的处理*/
void packageProcess(unsigned   char seqNum) {
	unsigned char cmd;
	unsigned char tmp = 0;
	unsigned int i;
	unsigned int num_bytes=0;
	unsigned int temp16;
	unsigned long start_address = address;
	
	cmd = msg_buffer[0];
	//版本信息
	if (cmd==CMD_SIGN_ON) {
		num_bytes = 11;
		msg_buffer[0] = CMD_SIGN_ON;
		msg_buffer[1] = STATUS_CMD_OK;
		msg_buffer[2] = 8;
		memcpy(msg_buffer+3,"STK500_2",8);
		}
	//参数设置
	else if (cmd==CMD_SET_PARAMETER) {
		num_bytes = 2;
		msg_buffer[0] = CMD_SET_PARAMETER;
		msg_buffer[1] = STATUS_CMD_OK;
		}
	//参数读取
	else if (cmd==CMD_GET_PARAMETER) {
		switch(msg_buffer[1]) {
			/*case PARAM_BUILD_NUMBER_LOW:
				tmp = CONFIG_PARAM_BUILD_NUMBER_LOW;
				break;
			case PARAM_BUILD_NUMBER_HIGH:
				tmp = CONFIG_PARAM_BUILD_NUMBER_HIGH;
				break;
			case PARAM_HW_VER:
				tmp = CONFIG_PARAM_HW_VER;
				break;
			case PARAM_SW_MAJOR:
				tmp = CONFIG_PARAM_SW_MAJOR;
				break;*/
			case PARAM_SW_MINOR:
				tmp = CONFIG_PARAM_SW_MINOR;
				break;
			case PARAM_RESET_POLARITY:
				tmp = resetPolarity;
				break;
			case PARAM_VTARGET:				//目标电压
				tmp = 50;
				break;	
			case PARAM_VADJUST:
				tmp = 50;				//参考电压
				break;
			/*case PARAM_TOPCARD_DETECT:
				tmp = TOP_CARD_STK520;
				break;
			case PARAM_CONTROLLER_INIT:
				tmp = paramControllerInit;
				break;
			case PARAM_SCK_DURATION:
				tmp = clockSpeed;
				break;*/
			default:
				tmp = CONFIG_PARAM_SW_MAJOR;
				break;
				}
		num_bytes = 3;
		msg_buffer[0] = CMD_GET_PARAMETER;
		msg_buffer[1] = STATUS_CMD_OK;
		msg_buffer[2] = tmp;
		}
	//读取时钟修正值
	/*else if (cmd==CMD_OSCCAL) {
		num_bytes = 2;
		msg_buffer[0] = CMD_OSCCAL;
		msg_buffer[1] = STATUS_CMD_OK;
		}*/
	//设置地址
	else if (cmd==CMD_LOAD_ADDRESS) {
		//address =  ((unsigned long)msg_buffer[1])<<24;
		address = ((unsigned long)msg_buffer[2])<<16;
		address |= ((unsigned long)msg_buffer[3])<<8;
		address |= ((unsigned long)msg_buffer[4]);
		num_bytes = 2;
		msg_buffer[0] = CMD_LOAD_ADDRESS;
		msg_buffer[1] = STATUS_CMD_OK;
		}
	//芯片擦除
	else if (cmd==CMD_CHIP_ERASE_ISP) {
		num_bytes = 2;
		msg_buffer[0] = CMD_CHIP_ERASE_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		}
	//进入编程模式
	else if (cmd == CMD_ENTER_PROGMODE_ISP) {
		num_bytes = 2;
		msg_buffer[0] = CMD_ENTER_PROGMODE_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		PORTB &= ~(1 << PB6);
		}
	//退出编程模式
	else if (cmd==CMD_LEAVE_PROGMODE_ISP) {
		num_bytes = 2;
		msg_buffer[0] = CMD_LEAVE_PROGMODE_ISP;
		msg_buffer[1] = STATUS_CMD_OK;	
			
		flag = 0;
		PORTB |= (1 << PB6);
		}
	/*写FLASH*/
		/*
		M128一页容量为256字节,而AVRISP一帧数据为128字节。
		为了仿止有奇数帧出现,所以必顺每一帧写入一次。
		每页数据将写入两次,但是下一帧数据不能覆盖上一帧数据。
		整个写入过程大概如下:
		1、写上半页:擦除一页,写入上半页数据。
		2、写全部页:擦除一页,写入整个页数据。
		*/
	else if (cmd==CMD_PROGRAM_FLASH_ISP) {
		/*缓存合并处理*/
		if ((address & 0xFF) == 0x00) {						/*判断是否为上半页*/
			boot_page_ew(address,0x03);						/*擦除页*/
			wait_page_rw_ok();								/*等待擦除完成 */
			/*加载上半页数据*/
			for (i = 0; i < SPM_PAGESIZE; i += 2) {			/*加载上半页数据*/
				temp16=msg_buffer[i+11];
				temp16<<=8;
				temp16+=msg_buffer[i+10];
				boot_page_fill(i,temp16);
				}
			}
		else {
			/*写下半页时不擦除页*/
			/*加载上半页数据*/
			for (i = 0; i < SPM_PAGESIZE; i += 2) {			/*填充在后半页,完成合并*/
				temp16=msg_buffer[i+11];
				temp16<<=8;
				temp16+=msg_buffer[i+10];
				boot_page_fill(i + 128, temp16);
				}
			}
		boot_page_ew(address,0x05);							/*将缓冲页数据写入一个Flash页 */
		wait_page_rw_ok();									/*等待写入完成 */
		address+=(SPM_PAGESIZE);
		num_bytes = 2;
		msg_buffer[0] = CMD_PROGRAM_FLASH_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		}
	//读FLASH
	else if (cmd==CMD_READ_FLASH_ISP) {
		for(i=0;i<READ_BLOCK_SIZE;i++) {
			msg_buffer[i+2] = read_program_memory (address+i,0x00);
			}
		address+=READ_BLOCK_SIZE;
		num_bytes = READ_BLOCK_SIZE + 3;
		msg_buffer[0] = CMD_READ_FLASH_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		msg_buffer[READ_BLOCK_SIZE + 2] = STATUS_CMD_OK;
		}
	//读熔丝位
	else if (cmd==CMD_READ_FUSE_ISP) {	
		switch(msg_buffer[2]) {
			case 0x50:
				msg_buffer[2] =	read_program_memory(0x0000,1);			//读熔丝位
				break;
			case 0x58:	
				msg_buffer[2] =	read_program_memory(0x0003,1);			//读高熔丝位
				break;
			default:
				break;
				}
		num_bytes = 4;
		msg_buffer[0] = CMD_READ_FUSE_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		msg_buffer[3] = STATUS_CMD_OK;
		}
	//写锁定位
	else if (cmd==CMD_PROGRAM_LOCK_ISP) {
		//write_lock_bits (msg_buffer[4]|0xC0);
		num_bytes = 3;
		msg_buffer[0] = CMD_PROGRAM_LOCK_ISP;
		msg_buffer[1] = STATUS_CMD_OK;		
		msg_buffer[2] = STATUS_CMD_OK;
		}
	//读锁定位
	else if (cmd==CMD_READ_LOCK_ISP) {
		msg_buffer[2] = read_program_memory(0x0001,1);
		num_bytes = 4;
		msg_buffer[0] = CMD_READ_LOCK_ISP;
		msg_buffer[1] = STATUS_CMD_OK;
		msg_buffer[3] = STATUS_CMD_OK;
		}
	//传送缓冲区数据
	if (num_bytes>0) {		
		putChar(MESSAGE_START);
		checkSum=MESSAGE_START;
		putChar(seqNum);
		checkSum^=seqNum;
		tmp=(num_bytes&0xFF00)>>8;
		putChar(tmp);
		checkSum^=tmp;
		tmp=num_bytes&0x00FF;
		putChar(tmp);
		checkSum^=tmp;
		putChar(TOKEN);
		checkSum^=TOKEN;
		for(i = 0; i < num_bytes; i++) {
			putChar(msg_buffer[i]);
			checkSum^=msg_buffer[i];
			}		
		putChar(checkSum);
		checkSum=0x00;
		}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -