attachment download第四步 使用JLINK仿真调试
在说JLINK仿真调试之前,我先说说我在main.c中写了点什么,为什么这样写,还有一个比较要命的问题的是如何初始化系统时钟。先说说我在main函数中写点什么,其实就是利用一个软件延时函数点亮然后熄灭一盏LED。第一步需要初始化该IO口的时钟,第二步把该IO口配置成推挽输出形式,第三步就是进入无限循环,不断置位和复位该IO口。
具体的代码如下
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
/* 初始化GPIOD时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
/* 初始化GPIOD的Pin_2为推挽输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
while (1)
{
/* 关闭LED1 */
GPIO_SetBits(GPIOD,GPIO_Pin_2);
/* 延时 */
Delay(0xAFFFF);
/* 点亮LED1 */
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
/* 延时 */
Delay(0xAFFFF);
}
}
这段代码其实也非常简单,也是我从新固件库的例程中直接修改过来的。我想请大家注意的是其中的一段英文注释,这段英文注释什么意思呢。“在运行main函数之前,系统时钟已经完成初始化工作,在main函数之前,通过调用启动代码运行了SystemInit函数,而这个函数位于system_stm32f10x.c”。根据文中的提示我们回到system_stm32f10x.c看看SystemInit如何初始化系统的。
在system_stm32f10x.c的开头便定义了系统的时钟频率,从下面的这段代码可以看出系统的频率被定义为72MHZ,这也是绝大多数STM32运行时的频率。
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
#endif
紧接着根据这个宏定义程序试图把系统时钟初始化为72MHz,代码有点冗长,这里就不一一列出。在SystemInit函数中,调用了SetSysClock函数,如果设定时钟的频率为72MHZ则SetSysCloc调用SetSysClockTo72函数,该函数和V2版本固件库中的各范例中的RCC_Configuration很相似,主要完成把外部时钟9倍频后分配给系统时钟,APB1时钟和APB2又由系统时钟分频获得。关键代码如下
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
在这里我想请大家注意一个细节,我个人觉得可能是ST开发人员的一个笔误,代码的原意是把HCLK时钟2分频过后提供给APB1时钟,但是注释的地方却写成了APB1的时钟和AHB的时钟频率相同。这里请大家指正,这个总线的时钟频率到底是多少!
从上面的分析可以看出,SystemInit并不需要用户调用,启动代码会自动执行,这样相当于少了一个RCC_Configuration函数的绝大多数内容。请大家注意是绝大多数内容而不是全部,但是请大家格外注意使用到的外设还是要第一时间使得该外设的时钟,像这样的一句千万不要忘了。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
让我们再回到Option选项卡。在选项卡中选择Debug选型卡,选择Cortex M3 J-LINK。一般在Run to main()上打钩,我个人除非特殊情况,一般不查看启动代码。如果第一次尝试V3.4库,倒可以验证一下SystemInit函数是不是自动运行了。
接着点击Utilities选项卡,选择Cortex-M3 J-LINK,然后在点击Setting按钮。
在点击Setting按钮出现的界面中,选择Flash Download选项卡,点击Add按钮,在众多的CPU型号中选择中等容量的STM32,即STM32F10X Med-density Flash。
紧接着点击Debug选项卡,当目标板和JLINK连接正确的话就图12的界面。在这里我强调,只有JLINK和目标板连接正确,并且目标板上电时,才会出现这样的界面。我个人一般选择SW下载模式,SW下载模式只需要2个IO口,加上VDD和GND只需要4个IO口。这样可以节约IO口和PCB板的空间。关于SW仿真接口和JTAG仿真接口的详细资料,请大家查看相关的文档了。
点击OK过后就可以放心大胆的开始debug了。可以通过设置断点或者单步运行,结合目标板的输出情况,验证程序是否按照要求运行。如果没有按照要求运行还是需要耐心的寻找问题。开始仿真后,程序停留在断点处,如图15所示。
用户1499087 2012-4-27 11:43
用户305149 2011-3-4 11:33