面对这个编译工程工具链的选择界面,许多人可能会感到迷茫,因为这里包含了许多容易出错的细节操作。
编译工具链的选择
选择编译工具链是工程编译的第一步。工具链的名称需严格遵循规定,至于路径,若是采用默认安装,那么它将指向一个特定的位置。我们必须精确地按照指定路径填写,否则我的同事就曾因路径错误而使得编译过程不断出现问题。尤其是在安装多个版本软件时,这一点尤为重要。这就像在众多岔路口精准找到正确的道路。同时,安装过程中的提示细节也需留意。
选定了工具链,接下来便是要精准定位和挑选工程文件。务必挑选与您芯片型号相匹配的文件,并在工程文件夹中仔细寻找那些以.c结尾的文件。这一环节必须认真细致,因为工程文件的正确定位直接关系到后续编译工作的顺利进行。设想一下,如果在项目团队中,新加入的成员未能准确找到所需的.c文件,那么他们在调试过程中可能会浪费大量的时间。
工程的设置操作
工程中有些项目已经预设好了,但仍有部分需要我们亲自调整。比如,芯片型号的挑选至关重要,一旦选错,就像零件不匹配,会导致后续操作无法顺利进行。脚本链接文件的选择同样不容忽视。另外,选择生成bin文件也很关键,这有助于我们了解代码的实际大小,并便于后续下载程序的工作配置。每个步骤都需精确操作,根据不同的芯片和需求,精确设定各项参数。
在实际操作中,设置参数时常常需要查阅详细的技术文档,或者向有经验的人士咨询。对于大型项目,尤其是多人协作的项目,事先统一参数设置是必要的,这样可以避免在后续整合过程中出现众多不兼容的问题。
main.c文件常见问题
在main.c文件中,有时会出现错误提示。正如文中所述,这些错误可能是因为标准库路径没有正确设置。在处理工单时,我们常常遇到技术人员对此感到困惑的情况。通常来说,只有正确配置了标准库路径,main.c文件才能正常运行。
解决这类问题需细致检查路径配置及关联的环境变量。有时,系统更新或软件升级后,先前正确的设置可能出错,这时必须重新核实设置是否与现有软件和系统环境相匹配。
Build中的设置
在Build环节,我们主要对工程编译的设置进行最终确认。这里涉及到是否在运行外部工具时编译工程的选项。按照我的操作习惯,我通常会在编译成功后再下载外部工具的程序,因此我会取消那个勾选。当然,如果不取消,也需要进行合理的设置,以确保只编译当前工程。在这个过程中,需要理解并操作英文参数。举个例子,有同事因为看不懂这些英文标识的含义,随意设置了参数,结果导致了编译失败。
在这个环节,我们必须考虑到多样化的编译需求。若是为了测试新功能,或是修改了某些代码而只想编译这些部分,那么我们的设置就必须更加精准和有针对性。
jlink相关的操作
在jlink操作中,需要挑选.exe文件,并对支持的芯片型号进行设置,这是一系列较为复杂的步骤。其中,设置芯片型号的部分在上面的程序下载环节已有提及,但务必确保准确性。在芯片研发的实际项目中,每种芯片都需对应特定的型号设置。此外,在创建外部工具的过程中,需认识到它与之前的jlink配置程序下载有相似之处。虽然这对初学者来说可能有些不易理解,但通过多次实践,便能掌握其中的关键。
在设置参数的部分,与程序下载时的参数存在差异,这里遗漏了一个命令参数。这一点必须准确把握,因为一旦参数设置错误,后续操作可能无法进行,或者产生错误结果。
最后的编译结果查找
/*----------------------------[数据类型定义]----------------------------*/
#define u32 unsigned int
#define u16 unsigned short int
#define u8 unsigned char
#define vlt volatile
/*----------------------------[头文件]----------------------------*/
#include
#include
/*----------------------------[寄存器位定义与操作]----------------------------*/
#define bit(X) (1<<X)
u32 range(u32 i, u32 j)
{
u32 bit_range=0;
for(;i<=j;i++)
{
bit_range |= 1<<i;
}
return (bit_range);
}
void Reg(volatile u32 * p, u32 range, u32 set)
{
u32 date;
date=*p;
date &= ~range;
date |= set;
*p=date;
}
/*----------------------------[外设基址]----------------------------*/
#define APB1 ((u32)0x40000000)
#define APB2 (APB1+0x00010000)
#define AHB (APB1+0x00018000)
/*----------------------------[GPIO]----------------------------*/
#define GPIOA (APB2+0x00000800)
#define GPIOB (APB2+0x00000C00)
#define GPIOC (APB2+0x00001000)
#define GPIOD (APB2+0x00001400)
#define GPIOE (APB2+0x00001800)
#define GPIOF (APB2+0x00001C00)
#define GPIOG (APB2+0x00002000)
struct GPIOX
{
volatile u32 CRL;
volatile u32 CRH;
volatile u32 IDR;
volatile u32 ODR;
volatile u32 BSRR;
volatile u32 BRR;
volatile u32 LCKR;
};
#define PA ((struct GPIOX *)GPIOA)
#define PB ((struct GPIOX *)GPIOB)
#define PC ((struct GPIOX *)GPIOC)
#define PD ((struct GPIOX *)GPIOD)
#define PE ((struct GPIOX *)GPIOE)
#define PF ((struct GPIOX *)GPIOF)
#define PG ((struct GPIOX *)GPIOG)
#define io(X) 1<<X
enum IOM
{
Is = 0 ,
If = 4 ,
Iud = 8 ,
Ih = 12,
O2gp = 2 ,
O2go = 6 ,
O2mp = 10,
O2mo = 14,
O10gp= 1 ,
O10go= 5 ,
O10mp= 9 ,
O10mo= 13,
O50gp= 3 ,
O50go= 7 ,
O50mp= 11,
O50mo= 15
};
void IOs(struct GPIOX * P, u32 io, enum IOM mode) // IOs(PC,io(13),O2gp);
{
int i;
u32 set_CR;
set_CR=P->CRL;
for(i=0;i<=7;i++)
{
if(io&(1<<i))
{
set_CR &= ~(0xF<<(i*4));
set_CR |= mode<<(i*4);
}
}
P->CRL=set_CR;
set_CR=P->CRH;
for(i=0;i<=7;i++)
{
if(io&(1<<(i+8)))
{
set_CR &= ~(0xF<<(i*4));
set_CR |= mode<<(i*4);
}
}
P->CRH=set_CR;
}
/*----------------------------[AFIO]----------------------------*/
struct AFIOX
{
volatile u32 EVCR;
volatile u32 MAPR;
volatile u32 EXTICR1;
volatile u32 EXTICR2;
volatile u32 EXTICR3;
volatile u32 EXTICR4;
};
#define AFIO ((struct AFIOX *)APB2)
/*----------------------------[RCC时钟]----------------------------*/
#define RCCA (AHB+0x00009000)
struct RCCX
{
volatile u32 CR;
volatile u32 CFGR;
volatile u32 CIR;
volatile u32 APB2RSTR;
volatile u32 APB1RSTR;
volatile u32 AHBENR;
volatile u32 APB2ENR;
volatile u32 APB1ENR;
volatile u32 BDCR;
volatile u32 CSR;
};
#define RCC ((struct RCCX *)RCCA)
#define SDIO bit(10) //AHBENR
#define FSMC bit(8)
#define CRC bit(6)
#define FLITF bit(4)
#define SRAM bit(2)
#define DMA_2 bit(1)
#define DMA_1 bit(0)
#define ADC_3 bit(15) //APB2ENR
#define USART_1 bit(14)
#define TIM8 bit(13)
#define SPI_1 bit(12)
#define TIM1 bit(11)
#define ADC_2 bit(10)
#define ADC_1 bit(9)
#define IOPG bit(8)
#define IOPF bit(7)
#define IOPE bit(6)
#define IOPD bit(5)
#define IOPC bit(4)
#define IOPB bit(3)
#define IOPA bit(2)
#define IOAF bit(0)
#define DAC bit(29) //APB1ENR
#define PWR bit(28)
#define BKP bit(25)
#define USB bit(23)
#define I2C_2 bit(22)
#define I2C_1 bit(21)
#define UART_5 bit(20)
#define UART_4 bit(19)
#define USART_3 bit(18)
#define USART_2 bit(17)
#define SPI_3 bit(15)
#define SPI_2 bit(14)
#define WWDG bit(11)
#define TIM7 bit(5)
#define TIM6 bit(4)
#define TIM5 bit(3)
#define TIM4 bit(2)
#define TIM3 bit(1)
#define TIM2 bit(0)
void AHBEN(struct RCCX * P, u32 choose, u32 m)
{
int i;
u32 set;
set=P->AHBENR;
for(i=0;i<=10;i++)
{
if(choose&(1<<i))
{
set &= ~(1<<i);
set |= m<<i;
}
}
P->AHBENR=set;
}
void APB2EN(struct RCCX * P, u32 choose, u32 m) // APB2EN(RCC, IOPA|IOPC, 1);
{
int i;
u32 set;
set=P->APB2ENR;
for(i=0;i<=15;i++)
{
if(choose&(1<<i))
{
set &= ~(1<<i);
set |= m<<i;
}
}
P->APB2ENR=set;
}
void APB1EN(struct RCCX * P, u32 choose, u32 m)
{
int i;
u32 set;
set=P->APB1ENR;
for(i=0;i<=29;i++)
{
if(choose&(1<<i))
{
set &= ~(1<<i);
set |= m<<i;
}
}
P->APB1ENR=set;
}
/*----------------------------[GPIO位带]----------------------------*/
#define PAo(X) *((volatile u32 *)(0x42000000+(GPIOA+0x0C-0x40000000)*32+4*X)) // PCo(13)=0;
#define PBo(X) *((volatile u32 *)(0x42000000+(GPIOB+0x0C-0x40000000)*32+4*X))
#define PCo(X) *((volatile u32 *)(0x42000000+(GPIOC+0x0C-0x40000000)*32+4*X))
#define PDo(X) *((volatile u32 *)(0x42000000+(GPIOD+0x0C-0x40000000)*32+4*X))
#define PEo(X) *((volatile u32 *)(0x42000000+(GPIOE+0x0C-0x40000000)*32+4*X))
#define PFo(X) *((volatile u32 *)(0x42000000+(GPIOF+0x0C-0x40000000)*32+4*X))
#define PGo(X) *((volatile u32 *)(0x42000000+(GPIOG+0x0C-0x40000000)*32+4*X))
#define PAi(X) *((volatile u32 *)(0x42000000+(GPIOA+0x08-0x40000000)*32+4*X))
#define PBi(X) *((volatile u32 *)(0x42000000+(GPIOB+0x08-0x40000000)*32+4*X))
#define PCi(X) *((volatile u32 *)(0x42000000+(GPIOC+0x08-0x40000000)*32+4*X))
#define PDi(X) *((volatile u32 *)(0x42000000+(GPIOD+0x08-0x40000000)*32+4*X))
#define PEi(X) *((volatile u32 *)(0x42000000+(GPIOE+0x08-0x40000000)*32+4*X))
#define PFi(X) *((volatile u32 *)(0x42000000+(GPIOF+0x08-0x40000000)*32+4*X))
#define PGi(X) *((volatile u32 *)(0x42000000+(GPIOG+0x08-0x40000000)*32+4*X))
volatile u32 * Bit(volatile u32 * p, u32 X)
{
return ((volatile u32 *)(0x42000000+((u32)p-0x40000000)*32+4*X));
}
#define Bit(p,X) (*Bit(p,X)) // Bit(&PC->ODR,13)=0;
/*----------------------------[Flash寄存器]----------------------------*/
#define Flash (AHB+0x0000A000)
struct FLASHX
{
volatile u32 ACR;
volatile u32 KEYR;
volatile u32 OPTKEYR;
volatile u32 SR;
volatile u32 CR;
volatile u32 AR;
volatile u32 Rsd;
volatile u32 OBR;
volatile u32 WRPR;
};
#define FLASH ((struct FLASHX *)Flash)
/*----------------------------[外部中断与事件]----------------------------*/
#define Exti (APB2+0x400)
struct EXTIX
{
volatile u32 IMR;
volatile u32 EMR;
volatile u32 RTSR;
volatile u32 FTSR;
volatile u32 SWIER;
volatile u32 PR;
};
#define EXTI ((struct EXTIX *)Exti)
/*----------------------------[异常与M3内核]----------------------------*/
#define Scs 0xE000E000
#define Nvic (Scs+0x0100)
#define Scb (Scs+0x0D00)
#define IDr (Scs+0x0FD0)
struct SCSX
{
vlt u32 Rsd0;
vlt u32 ICTR; //0x04
vlt u32 Rsd1[2];
vlt u32 STKCSR; //0x10
vlt u32 STKRDR; //0x14
vlt u32 STKCDR; //0x18
vlt u32 STKADR; //0x1C
};
struct NVICX
{
vlt u32 SETENA[8]; //0x00-0x1C
vlt u32 Rsd0[24];
vlt u32 CLRENA[8]; //0x80-0x9C
vlt u32 Rsd1[24];
vlt u32 SETPEND[8]; //0x100-0x11C
vlt u32 Rsd2[24];
vlt u32 CLRPEND[8]; //0x180-0x19C
vlt u32 Rsd3[24];
vlt u32 ACTIVE[8]; //0x200-0x21C
vlt u32 Rsd4[56];
vlt u8 PRI[240]; //0x300-0x3EF
vlt u32 Rsd5[644];
vlt u32 STIR; //0xE00
};
struct SCBX
{
vlt u32 CPUID; //0x00
vlt u32 ICSR; //0x04
vlt u32 VTOR; //0x08
vlt u32 ATRCR; //0x0C
vlt u32 SYSCR; //0x10
vlt u32 CFCR; //0x14
vlt u8 PRI[12]; //0x18-0x23
vlt u32 SHCSR; //0x24
vlt u8 MFSR; //0x28
vlt u8 BFSR; //0x29
vlt u16 UFSR; //0x2A
vlt u32 HFR; //0x2C
vlt u32 DFSR; //0x30
vlt u32 MMAR; //0x34
vlt u32 BFAR; //0x38
vlt u32 AFAR; //0x3C
vlt u32 Rsd0[20];
vlt u32 MPUTR; //0x90
vlt u32 MPUCR; //0x94
vlt u32 MPURNR0; //0x98
vlt u32 MPURNR1; //0x9C
vlt u32 MPURASR; //0xA0
vlt u32 Rsd1[19];
vlt u32 DHCSR; //0xF0
vlt u32 DCRSR; //0xF4
vlt u32 DCRDR; //0xF8
vlt u32 DEMCR; //0xFC
};
struct IDRX
{
vlt u32 PERIPHID4; //0x00
vlt u32 PERIPHID5; //0x04
vlt u32 PERIPHID6; //0x08
vlt u32 PERIPHID7; //0x0C
vlt u32 PERIPHID0; //0x10
vlt u32 PERIPHID1; //0x14
vlt u32 PERIPHID2; //0x18
vlt u32 PERIPHID3; //0x1C
vlt u32 PCELLID0; //0x20
vlt u32 PCELLID1; //0x24
vlt u32 PCELLID2; //0x28
vlt u32 PCELLID3; //0x2C
};
#define SCS ((struct SCSX *)Scs)
#define NVIC ((struct NVICX *)Nvic)
#define SCB ((struct SCBX *)Scb)
#define IDR ((struct IDRX *)IDr)
/*----------------------------[USART]----------------------------*/
#define Usart1 (APB2+0x3800)
#define Usart2 (APB1+0x4400)
#define Usart3 (APB1+0x4800)
#define Uart4 (APB1+0x4C00)
#define Uart5 (APB1+0x5000)
struct USARTX
{
vlt u32 SR;
vlt u32 DR;
vlt u32 BRR;
vlt u32 CR1;
vlt u32 CR2;
vlt u32 CR3;
vlt u32 GTPR;
};
#define USART1 ((struct USARTX *)Usart1)
#define USART2 ((struct USARTX *)Usart2)
#define USART3 ((struct USARTX *)Usart3)
#define UART4 ((struct USARTX *)Uart4)
#define UART5 ((struct USARTX *)Uart5)
void delay(vlt u32 num)
{
while(num--);
}
int main()
{
char * a;
char b;
/*printf和scanf函数必备的两行代码,不懂可以百度一下*/
setbuf(stdout, NULL);
setbuf(stdin, NULL);
APB2EN(RCC, IOPA, 1); //打开usart1的io口对应的时钟
//USART1配置//
IOs(PA, io(9), O50mp);
IOs(PA, io(10), If);
APB2EN(RCC, USART_1, 1);
USART1->DR=0; //要清空一下数据寄存器,不然第一个字符会乱码
Reg(&USART1->BRR, 0, (39<<4)|1); //115200波特率
Reg(&USART1->CR3, 0, range(6, 7));
Reg(&USART1->CR1, 0, bit(13)|bit(3)|bit(2));
a=malloc(8);
*a='9';
printf("rn这是一个寄存器版工程rn");
printf("123456%crn please input two char: ",*a);
scanf("%c %c",a,&b);
printf("rn The char what you input just now are: %c,%c",*a,b);
free(a);
APB2EN(RCC, IOPC, 1); //打开led对应io口的时钟
IOs(PC, io(13), O50gp); //配置对应led的io口
while(1)
{
PCo(13)=~PCo(13); //led闪烁
delay(888888);
}
}
/*----------------------------[系统初始化函数]----------------------------*/
void SystemInit()
{
Bit(&RCC->CR,16)=1;
while(! Bit(&RCC->CR,17));
Bit(&FLASH->ACR,4)=1;
Reg(&FLASH->ACR, bit(0)|bit(1), bit(1));
// FLASH->ACR &= ~(0x03);
// Bit(&FLASH->ACR,1)=1;
Bit(&RCC->CFGR,10)=1; //只对APB1二分频,其他两个默认不分频
Reg(&RCC->CFGR, range(16,21), range(15,16)|range(18,20)); //8*9=72M,ADC时钟为12M
// RCC->CFGR &= ~(0x3F0000);
// RCC->CFGR |= (0x1C0000|0x10000); //8*9=72M
Bit(&RCC->CR,24)=1;
while(Bit(&RCC->CR,25));
Reg(&RCC->CFGR, range(0,1), bit(1));
// RCC->CFGR &= ~(0x3);
// Bit(&RCC->CFGR,1)=1;
while(! Bit(&RCC->CFGR,3));
}
完成前面的操作后,便进入等待编译结果的阶段。需要等待Java编译结束,随后在指定的目录中寻找那个jar文件。注意,不同版本的插件文件名可能不同,以我的6.7.0.2版本为例,文件名中就明确包含了版本号。在寻找过程中,务必细心,因为一旦出错,可能无法找到正确的文件,或者找到错误的版本,这会影响到后续对文件的使用,甚至可能引发兼容性问题。
#define TI (*(unsigned int *)0x4227001C) //发送结束标志: TXE
#define RI (*(unsigned int *)0x42270014) //接收标志: RXNE
#define SBUF (*(unsigned int *)0x40013804) //接收发送寄存器,即: USART1->DR
/**************************************************************************
这个文件仅适用于stm32f10x系列。
这个为GCC版本的printf和scanf函数的重定义,不适用于keli的。
2,3行用了位带操作。
特别提醒,使用这个重定义printf和scanf函数文件不需要你开启USART_IT_TXE,USART_IT_TC,USART_IT_RXNE这三个中断,不然会扰乱printf和scanf函数的工作。
**************************************************************************/
int __io_putchar(int ch) //与printf函数相关的函数
{
TI=0;
/* Write a character to the USART */
SBUF = ch;
/* Loop until the end of transmission */
while(!TI);
return ch;
}
void Usend(unsigned char ch) //用于回显的函数
{
SBUF = ch;
while (!TI);
}
int __io_getchar(void) //与scanf函数相关的函数
{
int temp = 0;
Gagain:
while (!RI);
temp = SBUF;
RI=0;
if (temp == 0x0d)
{
Usend(0x0a);
Usend(0x0d);
}
else if (temp == 0x08)
{
goto Gagain;
}
else
{
Usend(temp);
}
return (temp);
}
尽管这些步骤显得繁杂且复杂,但只要我们逐一认真细致地处理每一个环节,任务还是可以顺利完成的。在工程编译的过程中,你是否也遇到了一些独特的问题?期待大家在评论区分享自己的经验或是提出疑问。同时,别忘了点赞并转发这篇文章。