自己用C语言写单片机PIC18 serial bootloader

发布者:MoonlightStar最新更新时间:2017-01-20 来源: eefocus关键字:C语言  单片机  PIC18  serial  bootloader 手机看文章 扫描二维码
随时随地手机看文章

  HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J

  完成PIC16 bootloader (详细情况请阅读我的上一篇随笔《自己用C语言写单片机PIC16 serial bootloader》) 后,接着就开始写PIC18的UART bootloader。事实上我写了HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J 两种bootloader。 一种给PIC18F, 另一种给PIC18FJ。两种bootloader除了在实现上有一点不同,大小也不同外,其他都差不多。都是模仿HI-TECH PICC bootloader实现的, 都是放置在程序存储器的头部,电脑端的程序都是用超级终端传送应用程序的Hex文件。在继续之前,先讲讲PIC18F和PIC18FJ的区别。

  PIC18F和PIC18FJ的区别

  PIC18F和PIC18FJ一个不同点是CONFIG BITS的烧写位置。对于PIC18F, CONFIG BITS被映射到程序存储器300000h (虚拟地址)开始的单元中。对于PIC18FJ,CONFIG BITS被烧写到程序存储器的底部(真实地址),每次上电自动会被映射到程序存储器300000h (虚拟地址)开始的单元中,所以对于PIC18FJ, 更新了CONFIG BITS,reset后才生效。

  

  Interrupt Vector Remap

  由于bootloader 位于程序存储器的头部,需要对Interrupt Vector进行remap. 代码如下。

  #asm
    PSECT intcode
    goto APP_START + 0x8    PSECT intcodelo
    goto APP_START + 0x18  #endasm

  HyperBootloader_PIC18_None_J 主要代码段

  HyperBootloader_PIC18_None_J 每接收一行的超级终端发过来的Hex数据,一个一个程序字地烧录。具体实现的主要代码段如下。



    for(;;)        // loop until end of file    {        while (RCREG!=':');        // wait for start of hex file line

        while(!TXSTAbits.TRMT);
        TXREG=':';      // the prompt to download a new program
        cksum = bcount = g2x();        // get the byte count#if _EEPROMSIZE > 256
        EEADRH = TBLPTRH = g2x();        // get the address#else
        TBLPTRH = g2x();#endif
        TBLPTRL = EEADR = g2x();

        DO_NOT_INCREMENT = 1;
        rectype = g2x();    // get the record type
        switch(rectype)
        {        case DATA:    // ldata record
            #if (PROG_START > 0x200) || defined(__PIC18FX520)    
// to protect bootloader from being overwritten
            if( (FLASH) && (TBLPTRU==0) && (TBLPTRH < (unsigned char)(PROG_START>>8)) )    
// to protect bootloader from being overwritten
                break;        // if bootloader is threatened, skip this
            #endif
        clear_buffer();            while(bcount--)
            {
                TABLAT = EEDATA = buff[(EEADR&(_FLASH_WRITE_SIZE-1))] = g2x();     // get the data

                if((CONFIG)||(EEPROM))
                {                    if(CONFIG) // EEPROM/config. write byte at a time                    {
                        table_write();
                    }                    //zap();                }                else
                {                    if((EEADR & (_FLASH_WRITE_SIZE-1)) == (_FLASH_WRITE_SIZE-1))  //program/IDLOCs flash bytes at a time                    {
                        flash8();
                        clear_buffer();
                    }
                }
                EEADR++;
            }            if(((EEADR&(_FLASH_WRITE_SIZE-1))!=0)&&(FLASH)&&(!CONFIG))
                flash8();
            checksum();            break;        case END:    // end of hex file            checksum();
            TXSTA = 0x02;     //reset USART before jump to application
            RCSTA = 0x00;
            (*((void(*)(void))PROG_START))(); // jump to new program
            break;        case EXTEND_ADDRESS:    // extended address record
            while(bcount--)
            {
                EEADR=g2x();    // determines whether EE, Config or ID             }
            EEPGD=1;            if(EEADR==0xF0)
                EEPGD=0;    // select for EEPROM
            CFGS=0;            if((EEADR&0xF0)==0x30)
                CFGS=1;        // select for config write
            TBLPTRU=EEADR;
            checksum();            break;
        }
    }


  HyperBootloader_PIC18_J 主要代码段

  HyperBootloader_PIC18_J 每接收一行的超级终端发过来的Hex数据,在存到block数组中,block满了,再整个block地烧录。具体实现的主要代码段如下。


for (;;)
    {        while (RCREG != ':');        while(!TXSTAbits.TRMT);
        TXREG=':';    // the prompt to download a new program
        cksum = bcount = g2x();
        data_buffer[LEN_INDEX] = bcount;
        data_buffer[ADDRH_INDEX] = g2x();
        data_buffer[ADDRL_INDEX] = g2x();
        rectype = g2x();        switch(rectype)
        {            case DATA:                while (bcount--)
                {
                    data_buffer[LEN_INDEX + data_index + 1] = g2x();
                    data_index++;
                }
                checksum();
                EECON1 = PGM_WRITE;
                WriteMem();                break;            case END:
                checksum();                if (block_start)
                {
                    WriteStart();
                    resetBlockBuffer();
                    block_start = 0;
                }
                TXSTA = 0x02; //reset USART before jump to application
                RCSTA = 0x00;
                asm("goto "___mkstr(APP_START));                break;            case EXTEND_ADDRESS:
                g2x();
                data_buffer[ADDRU_INDEX] = g2x();
                checksum();                break;
        }
        data_index = 0;
    }


  如何使用

  1. 使用XC8编译HyperBootloader_PIC18_J 或HyperBootloader_PIC18_None_J。

  2. 使用pickit3烧录HyperBootloader_PIC18_J 或HyperBootloader_PIC18_None_J的Hex文件到目标板中。

  3. 拔除pickit3烧录器,连接目标板与PC的串口,打开超级终端,设置如下:9600-8-None-1-None, Line Delay-20ms。

  4. 重启目标板,超级终端会出现Booting... 字样。

  5. 6秒内,在超级终端窗口中按下键盘上任何按键,会出现">"(6秒内没按键,会自动跳转到用户的应用程序中去)。

  6. 打开Send Text File对话框,选择期望烧录的应用程序hex文件(由于bootloader在程序存储器的头部,所以应用程序需要在编译前设置XC8的Code offset, 如果是使用HyperBootloader_PIC18_J,设置为400, 如果是使用HyperBootloader_PIC18_None_J, 设置为300),点击确认, HyperBootloader会将接收到的数据传回到电脑超级终端上,并将数据烧录到目标板程序存储器的正确位置。

  7. 烧录完毕,再次重启目标板,超级终端显示完Booting ......,就自动跳到应用程序中,目标板开始正常运行应用程序。

  之后每次更新应用程序,只需重复步骤 4 ~ 7 就可以了。

  主要特性

  HyperBootloader_PIC18_J 和 HyperBootloader_PIC18_None_J 有以下主要特性

  1. C语言写的,XC8 编译。

  2. 非常容易移植。

  3. 支持FLASH烧写

  4. 可支持EEPROM烧写。

  5. 支持CONFIG BITS/IDLOC 烧写。

 


关键字:C语言  单片机  PIC18  serial  bootloader 引用地址:自己用C语言写单片机PIC18 serial bootloader

上一篇:自己用C语言写单片机PIC16 serial bootloader
下一篇:自己用C语言写dsPIC / PIC24 serial bootloader

推荐阅读最新更新时间:2024-03-16 15:31

基于51单片机按键控制喇叭发出多种声音
具体实现功能: 51单片机按键控制喇叭发出多种声音。 设计介绍 51单片机简介 51单片是一种低功耗、高性能CMOS-8位微控制器,具有8K可编程Flash存储器,使得其为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 51系列单片机具有以下标准功能: 8k字节Flash,512字节RAM, 32位I/O口线,看门狗定时器, 内置4KB EEPROM, MAX810复位电路, 三个16位定时器/计数器, 一个6向量2级中断结构, 全双工串行口。 另外, 51系列在空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机停止工作,直到下一个中
[单片机]
基于51<font color='red'>单片机</font>按键控制喇叭发出多种声音
飞思卡尔16位单片机(三)——GPIO输出功能测试
一、GPIO介绍 GPIO是单片机最常用的功能,XEP100单片机的并行I/O的资源很丰富,XEP100的IO有PORTA、PORTB、PORTH、PORTJ、PORTM、PORTP、PORTS、PORTT、PORTK和PORTE共10组IO。这些I/O口除了具有通用I/O功能外,还分别具有专用I/O的功能。可以根据需要进行设置,专用I/O功能启用后,通用I/O功能自动关闭。 在使用单片机的并行I/O时要进行一些设置,主要的设置如下所示: 1功能设置 每个I/O子系统都有一个功能设置寄存器,其中的几个位用于部分或者全部引脚的功能设定,设定为专用功能后,方向设置功能可能自然禁止,但上拉、下拉及降功率驱动功能一般仍然有效,具体
[单片机]
飞思卡尔16位<font color='red'>单片机</font>(三)——GPIO输出功能测试
基于ATmega8单片机的红外导盲系统设计
0 引言 盲人在行走引导方面有很大的困难,目前盲人的导盲主要是依靠手杖敲击路面来判断前方是否有可行的路线,这种方法效率不高,且有一定的局限性,无法告知盲人周围障碍物的分布情况和距离。本文对采用光电式的导盲方式进行了探索研究,提出了一种单片机红外避障导盲系统的简便方案,通过单片机采集红外测距传感器的信号,判断出使用者周围障碍物的方位和距离,通过语音芯片发出报警提示信息。该系统具有设计简便小巧,稳定可靠等特点。 1 红外距离传感器的选择 常见的红外距离传感器是运用红外发射管发射出一束红外光,经前方的物体反射后在发射管同一侧用红外接收管检测反射光的强度,从而大致判断出传感器和障碍物的距离。但这种方法对距离的判断误差比较大,因为
[单片机]
基于ATmega8<font color='red'>单片机</font>的红外导盲系统设计
51单片机 LCD1602
LCD1602算是很简单的人机交互,有了这家伙,从此学习不再寂寞了,至少有这家伙的陪伴。注释很详细的,看代码。 原理图: 代码: #include reg52.h #define uint unsigned int #define uchar unsigned char //端口声明 sbit duanxuan=P2^6; sbit weixuan=P2^7; sbit lcd1602_E=P3^4; sbit lcd1602_RS=P3^5; //显示数据数组 uchar table1 = ^_^I LOVE MCU^_^ ; //第一行显示数据 uchar tabl
[单片机]
基于PIC单片机的直流电机测速程序设计
在捕捉模式下,当对应的CCPx引脚上有事件发生时,CCPRxH:CCPRxL寄存器对将捕捉TMR1寄存器或TMR3寄存器的16位值。事件定义为下列情况之一: 每个下降沿 每个上升沿 每4个上升沿 每16个上升沿 u通过模式选择位CCPxM3:CCPxM0(CCPxCON《3:0》)选择事件类型。当一个捕捉发生时,中断请求标志位CCPx IF 置1,它必须用软件清零。如果在读取寄存器CCPRx之前发生了另一个捕捉,那么之前捕捉的值将被新捕捉的值覆盖。 u在捕捉模式下,应该通过将相应的TRIS方向位置1来将CCPx引脚配置为输入 注: 如果RB3/CCP2或RC1/CCP2引脚被配置为输出,对该端口的写操作会产生捕捉条件。 u
[单片机]
基于PIC<font color='red'>单片机</font>的直流电机测速程序设计
51单片机基础之流水灯(一)
代码: #include reg52.h //不再赘述 #define LED P2 //宏定义P2端口,偏于直接操作 void delay(unsigned int u16) //不再赘述 { while(u16--); } void main(void) { int i; //定义一个变量 while(1) { for(i=0;i 8;i++) //循环执行八次 { LED=~(0x01 i); //第一次执行的时候左移一位,第二次左移两位,第三次左移三位,以此类推
[单片机]
51<font color='red'>单片机</font>基础之流水灯(一)
STM32L4单片机无法进入低功耗模式的原因及解决方法
1.引言 STM32 L4 系列作为一款高性能的低功耗芯片,具有强大的运算处理性能和极低的运行和待机功耗,广泛应用于各种需要节能设备上。 2. 问题描述 客户使用 STM32L431 作为主控项目开发电子烟产品,使用了 ST 的 HAL 软件库开发。各种驱动功能正常。空闲时进入待机状态。在研发阶段测试时一切正常,但是批量生产时发现产品无法进入低功耗或者说表现为耗电过大。 3. 问题分析与定位 首先查找软件设计本身,包括各种外设的配置以及进入低功耗前的各种处理,并未发现任何异常,随即简化软件在评估板上烧录代码,然后连接电流表,功耗一切正常。经过多次验证,每次都能进入低功耗。 这样看起来就非常奇怪了,客户的硬件也没什么特殊地方。后
[单片机]
STM32L4<font color='red'>单片机</font>无法进入低功耗模式的原因及解决方法
51单片机内核的中断基础知识
51内核的最基础的中断源请求有外部中断、定时器中断和串口中断,这也是学习和开发者最长用的。当然还有其他的中断源,比如ADC、SPI、PWM等。以外部中断0为例,在编程中常使用的方式为: void INT0()interrupt 0 using 1 { …… } 在这里特别做上笔记:其中前面的void INT0() 只是代表一个普通没有形参的函数而已,函数名写成什么都是可以的,这个到不重要。那么后面的就一个一个词的扣把:(2-1-i-c-中国-电子网,防抓取) 其中 interrupt n 组成一组,n用来指明中断号,在函数后使用了interrupt关键字后,就会自动的生成中断向量,51内核中断号如下图,这是
[单片机]
51<font color='red'>单片机</font>内核的中断基础知识
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved