以前使用STM32单片机的时候,生成的HEX文件,代码存储都是从0地址开始依次递增存储的,但是最近再使用PIC单片机的时候却发现这个单片机有点不一样。搞了好久才搞清楚了PIC单片机代码存储的原理。
下面就使用PIC18F46K80单片机来演示一下这个单片机HEX文件中代码存储的规律。
使用MPLAB X IDE新建一个工程,编写一个简单的LED程序
/*@ 配置字部分,可通过菜单栏Window/PIC存储器视图/Configuration Bits来配置并生成配置字代码*********************************/
//CONFIG1L
#pragma config RETEN = OFF // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit)),禁止超低功耗稳压器
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep),休眠期间 LF-INTOSC 处于高功耗模式
#pragma config SOSCSEL = DIG // SOSC Power Selection and mode Configuration bits (Digital (SCLKI) mode),SOSC 功耗选择和模式配置位,数字 ( SCLKI)模式;使能 RC0 和 RC1 的 I/O 端口功能
#pragma config XINST = OFF // Extended Instruction Set (Disabled),扩展指令集使能位,禁止指令集扩展和变址寻址模式 (传统模式)
// CONFIG1H
#pragma config FOSC = HS1 // Oscillator (HS oscillator (Medium power, 4 MHz - 16 MHz)),HS振荡器,中等功耗
#pragma config PLLCFG = ON // PLL x4 Enable bit (Enabled),打开PLL功能,系统时钟4倍频,变为32MHz
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled),禁止故障保护时钟监视器
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled),禁止双速启动
// CONFIG2L
#pragma config PWRTEN = OFF // Power Up Timer (Disabled),禁止上电延时定时器
#pragma config BOREN = SBORDIS // Brown Out Detect (Enabled in hardware, SBOREN disabled),只能由硬件使能欠压复位
#pragma config BORV = 3 // Brown-out Reset Voltage bits (1.8V),欠压复位电压选择为1.8v
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected),选择ZPBORMV而不是BORMV
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled),关闭看门狗功能
//#pragma config WDTEN = SWDTDIS // Watchdog Timer (WDT enabled in hardware; SWDTEN bit disabled),由硬件使能WDT,禁止SWDTEN位
#pragma config WDTPS = 256 // Watchdog Postscaler (1:256),看门狗后分频1:256,溢出时间1.024s
// CONFIG3H
#pragma config CANMX = PORTB // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively),1 = CANTX 和 CANRX 引脚分别位于 RB2 和 RB3 上
#pragma config MSSPMSK = MSK7 // MSSP address masking (7 Bit address masking mode),1 = 使能 7 位地址掩码模式
#pragma config MCLRE = ON // Master Clear Enable (MCLR Enabled, RE3 Disabled),使能MCLR复位功能
// CONFIG4L
#pragma config STVREN = ON // Stack Overflow Reset (Enabled),堆栈满/下溢导致复位
#pragma config BBSIZ = BB2K // Boot Block Size (2K word Boot Block size),引导区大小选择2K
// CONFIG5L
#pragma config CP0 = OFF // Code Protect 00800-01FFF (Disabled),代码保护位
#pragma config CP1 = OFF // Code Protect 02000-03FFF (Disabled),代码保护位
#pragma config CP2 = OFF // Code Protect 04000-05FFF (Disabled),代码保护位
#pragma config CP3 = OFF // Code Protect 06000-07FFF (Disabled),代码保护位
// CONFIG5H
#pragma config CPB = OFF // Code Protect Boot (Disabled),引导区不受代码保护
#pragma config CPD = OFF // Data EE Read Protect (Disabled),数据EEPROM不受代码保护
// CONFIG6L
#pragma config WRT0 = OFF // Table Write Protect 00800-01FFF (Disabled),写保护位
#pragma config WRT1 = OFF // Table Write Protect 02000-03FFF (Disabled),写保护位
#pragma config WRT2 = OFF // Table Write Protect 04000-05FFF (Disabled),写保护位
#pragma config WRT3 = OFF // Table Write Protect 06000-07FFF (Disabled),写保护位
// CONFIG6H
#pragma config WRTC = OFF // Config. Write Protect (Disabled),配置寄存器不受写保护
#pragma config WRTB = OFF // Table Write Protect Boot (Disabled),引导区不受写保护
#pragma config WRTD = OFF // Data EE Write Protect (Disabled),数据EEPROM不受写保护
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protect 00800-01FFF (Disabled),表读保护位
#pragma config EBTR1 = OFF // Table Read Protect 02000-03FFF (Disabled),表读保护位
#pragma config EBTR2 = OFF // Table Read Protect 04000-05FFF (Disabled),表读保护位
#pragma config EBTR3 = OFF // Table Read Protect 06000-07FFF (Disabled),表读保护位
// CONFIG7H
#pragma config EBTRB = OFF // Table Read Protect Boot (Disabled),引导区不受写保护
#include <xc.h>
#define uchar unsigned char
#define uint unsigned int
#define led_blue LATBbits.LATB1
void delay_ms(uint m)
{
unsigned int a,b;
for(b=m;b>0;b--)
{
for(a=796;a>0;a--);
}
}
int main(void)
{
ANCON1=0x00; //PORTB带模拟输入功能的引脚全部配置为数字IO
TRISBbits.TRISB1=0; //RB1配置为输出
led_blue=1;
while(1)
{
led_blue=0; //蓝灯点亮
delay_ms(100);
led_blue=1; //蓝灯熄灭
delay_ms(100);
}
return 0;
}
接下来编译代码,生成hex文件。
使用notepad++ 打开hex文件
可以看到默认生成的代码存放地址都是从0x1000开始的,如果要修改存储地址的话需要再编译器项目属性里面设置ROM的地址范围。
打开项目属性由两种方法
第一种直接再File菜单中选择
第二种直接点击项目属性旁边的齿轮图标
打开项目属性设置
左边选择XC8 linker,右边操作类型选择Memory model,然后再ROM ranges 后面输入代码存放的地址范围,这个地址根据自己的项目情况设置。这里设置的范围为0到7FF之间。点击应用,再点击确定按钮。重新编译代码,查看hex文件。
这时候代码的存储位置变了,但是不是从0地址开始存储,而是从7FF地址前面了。没有存储到最前面,而是存储到了最后面一段。这个原因在网上找了好久才搞明白。当程序中没有中断的时候,代码存储的位置是编译器自动存放的,不一定是按照顺序从0开始存放的。要想代码从0开始存放,就需要在代码中添加中断。
下来给代码中添加一个串口中断函数
#include <xc.h>
#define uchar unsigned char
#define uint unsigned int
#define led_blue LATBbits.LATB1
uchar USART_Rdata = 0x00; // 为接收串口数据流而定义的变量
void usart1_init(void)
{
TXSTA1bits.SYNC = 0; // 异步模式
TXSTA1bits.BRGH = 0; // 选择低速波特率模式
TXSTA1bits.TX9 = 0; // 选择8位发送模式
TXSTA1bits.TXEN = 1; // 使能发送
RCSTA1bits.SPEN = 1; // 使能串口,1 = 使能串口 (将 RXx/DTx 和 TXx/CKx 引脚配置为串口引脚)
RCSTA1bits.CREN = 1; // 连续接收使能
RCSTA1bits.RX9 = 0; // 选择8位接收模式
BAUDCON1bits.BRG16 = 1; // 选择16位波特率发生器,SYNC=0,BRGH=0,BRG16=1,波特率寄存器值=fosc/(16*19200))-1=32000000hz/(16*19200)-1=103.16,取值103
// SPBRG1=103; //配置波特率为19200(器件工作于32MHz条件下)
SPBRG1 = 207; // 波特率9600 32000000/(16*9600)-1=207.3333333333
SPBRGH1 = 0;
PIE1bits.RC1IE = 1; // 开usart1接收中断
PIR1bits.RC1IF = 0; // 清零usart1接收中断标志位
PIE1bits.TX1IE = 0; // 关闭发送中断,中断配置,根据需要来设置
PIR1bits.TX1IF = 0; // 清零发送中断标志位
INTCONbits.PEIE = 1; // 打开外设中断
INTCONbits.GIE = 1; // 打开总中断
}
void __interrupt() ISR(void)
{
if (PIE1bits.RC1IE && PIR1bits.RC1IF)
{
USART_Rdata = RCREG1;
PIR1bits.RC1IF = 0;
}
}
void delay_ms(uint m)
{
unsigned int a,b;
for(b=m;b>0;b--)
{
for(a=796;a>0;a--);
}
}
int main(void)
{
ANCON1=0x00; //PORTB带模拟输入功能的引脚全部配置为数字IO
TRISBbits.TRISB1=0; //RB1配置为输出
led_blue=1;
usart1_init();
while(1)
{
led_blue=0; //蓝灯点亮
delay_ms(100);
led_blue=1; //蓝灯熄灭
delay_ms(100);
}
return 0;
}
重新编译代码,查看hex文件。
此时代码的存储就从0地址开始依次递增了。
如果要设置代码的偏移地址的话,也可以在项目属性中设置。
左边选择XC8 Linker,右边选择Additional options,在代码偏移Codeoffset处设置偏移地址,这里设置为0x100,点击应用,在点确定。
重新编译在查看HEX文件
可以看出代码的存放地址就改到了从0x100地址开始存放了。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_20222919/article/details/145069924
|