打印

【STM32F0实验】第一个KEIL自带的示例实验分析

[复制链接]
6016|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaoyang9992006|  楼主 | 2012-8-20 22:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
打开keil目录找到C:\Keil\ARM\Boards\ST\STM32F0-Discovery\
下面有两个Keil自带的探索板子的示例演示程序,很好玩的。
打开后可以看到包含启动代码和源程序代码以及说明文档
启动代码就当是启动系统必须的部分吧,我们先懒得看他们。
看到SourceFiles感到很亲切,玩51单片机都是这个部分属于我们的。
看第一个示例Blinky,看名字就知道是让LED闪烁的程序。跑马灯等都是这一类程序。
看文件LED.c的代码
/*----------------------------------------------------------------------------
* Name:    LED.c
* Purpose: Low level LED functions
* Note(s):
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* This software is supplied "AS IS" without warranties of any kind.
*
* Copyright (c) 2012 Keil - An ARM Company. All rights reserved.
*----------------------------------------------------------------------------*/
#include <stm32f0xx.h>                  /* STM32F0xx Definitions              */
#include "LED.h"
const unsigned long led_mask[] = {1UL << 8, 1UL << 9};
/*-----------------------------------------------------------------------------
*      LED_Init:  Initialize LEDs
*
* Parameters: (none)
* Return:     (none)
*----------------------------------------------------------------------------*/
void LED_Init (void) {
  /* Enable clock for GPIOC                                                   */
  RCC->AHBENR |= (1UL << 19);
  /* Configure LED (PC.8..9) pins as push-pull outputs */
  GPIOC->MODER  &= ~((3UL << 2 * 8) | (3UL << 2 * 9));
  GPIOC->MODER  |=  ((1UL << 2 * 8) | (1UL << 2 * 9));
  GPIOC->OTYPER &= ~((1UL <<     8) | (1UL <<     9));
}

/*-----------------------------------------------------------------------------
*      LED_On: Turns on requested LED
*
* Parameters:  num - LED number
* Return:     (none)
*----------------------------------------------------------------------------*/
void LED_On (uint32_t num) {
  if (num < LED_NUM) {
    GPIOC->BSRR |= (led_mask[num]);
  }
}
/*-----------------------------------------------------------------------------
*       LED_Off: Turns off requested LED
*
* Parameters:  num - LED number
* Return:     (none)
*----------------------------------------------------------------------------*/
void LED_Off (uint32_t num) {
  if (num < LED_NUM) {
    GPIOC->BSRR |= (led_mask[num] << 16);
  }
}
/*-----------------------------------------------------------------------------
*       LED_Val: Write value to LEDs
*
* Parameters:  val - value to be displayed on LEDs
* Return:     (none)
*----------------------------------------------------------------------------*/
void LED_Out (uint32_t val) {
  int i;
  for (i = 0; i < LED_NUM; i++) {
    if (val & (1<<i)) {
      LED_On (i);
    } else {
      LED_Off(i);
    }
  }
}

以上全部是子函数,因为没有主函数main()
而我们的C语言是以main函数为顺序执行的。
看到blinky.c里面含有main,我们以main函数来观察整个工程。
/*----------------------------------------------------------------------------
* Name:    Blinky.c
* Purpose: LED Flasher
* Note(s):
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* This software is supplied "AS IS" without warranties of any kind.
*
* Copyright (c) 2012 Keil - An ARM Company. All rights reserved.
*----------------------------------------------------------------------------*/
//#include <stdio.h>
#include "STM32F0xx.h"
#include "LED.h"

volatile uint32_t msTicks;                /* counts 1ms timeTicks       */
/*----------------------------------------------------------------------------
  SysTick_Handler
*----------------------------------------------------------------------------*/
void SysTick_Handler(void) {
  msTicks++;
}
/*----------------------------------------------------------------------------
  delays number of tick Systicks (happens every 1 ms)
*----------------------------------------------------------------------------*/
void Delay (uint32_t dlyTicks) {                                             
  uint32_t curTicks;
  curTicks = msTicks;
  while ((msTicks - curTicks) < dlyTicks);
}

/*----------------------------------------------------------------------------
  Function that initializes Button pins
*----------------------------------------------------------------------------*/
void BTN_Init(void) {
  RCC->AHBENR  |= ((1UL << 17) );               /* Enable GPIOA clock         */
  GPIOA->MODER    &= ~((3UL << 2*0)  );         /* PA.0 is input              */
  GPIOA->OSPEEDR  &= ~((3UL << 2*0)  );         /* PA.0 is Low Speed          */
  GPIOA->PUPDR    &= ~((3UL << 2*0)  );         /* PA.0 is no Pull up         */
}
/*----------------------------------------------------------------------------
  Function that read Button pins
*----------------------------------------------------------------------------*/
uint32_t BTN_Get(void) {
return (GPIOA->IDR & (1UL << 0));
}

/*----------------------------------------------------------------------------
  set HSI as SystemCoreClock (HSE is not populated on STM32L-Discovery board)
*----------------------------------------------------------------------------*/
void SystemCoreClockSetHSI(void) {
  RCC->CR |= ((uint32_t)RCC_CR_HSION);                      /* Enable HSI                        */
  while ((RCC->CR & RCC_CR_HSIRDY) == 0);                   /* Wait for HSI Ready                */
  RCC->CFGR = RCC_CFGR_SW_HSI;                              /* HSI is system clock               */
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);   /* Wait for HSI used as system clock */
  FLASH->ACR  = FLASH_ACR_PRFTBE;                           /* Enable Prefetch Buffer            */
  FLASH->ACR |= FLASH_ACR_LATENCY;                          /* Flash 1 wait state                */

  RCC->CFGR |= RCC_CFGR_HPRE_DIV1;                          /* HCLK = SYSCLK                     */
  RCC->CFGR |= RCC_CFGR_PPRE_DIV1;                          /* PCLK = HCLK                       */
  RCC->CR &= ~RCC_CR_PLLON;                                 /* Disable PLL */
  /*  PLL configuration:  = HSI * 12 = 48 MHz */
  RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
  RCC->CFGR |=  (RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL12);
            
  RCC->CR |= RCC_CR_PLLON;                                  /* Enable PLL                        */
  while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP();            /* Wait till PLL is ready            */
  RCC->CFGR &= ~RCC_CFGR_SW;                                /* Select PLL as system clock source */
  RCC->CFGR |=  RCC_CFGR_SW_PLL;   
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);   /* Wait till PLL is system clock src */
}

/*----------------------------------------------------------------------------
  MAIN function
*----------------------------------------------------------------------------*/
int main (void) {
  int32_t num = -1;
  int32_t dir =  1;
uint32_t btns = 0;
  SystemCoreClockSetHSI();
  SystemCoreClockUpdate();                      /* Get Core Clock Frequency   */
  if (SysTick_Config(SystemCoreClock / 1000)) { /* SysTick 1 msec interrupts  */
    while (1);                                  /* Capture error              */
  }
  LED_Init();
  BTN_Init();                             

  while(1) {                                    /* Loop forever               */
    btns = BTN_Get();                           /* Read button states         */
    if (btns != (1UL << 0)) {
      /* Calculate 'num': 0,1,...,LED_NUM-1,LED_NUM-1,...,1,0,0,...  */
      num += dir;
      if (num == LED_NUM) { dir = -1; num =  LED_NUM-1; }
      else if   (num < 0) { dir =  1; num =  0;         }
      LED_On (num);
      Delay( 50);                               /* Delay 50ms                 */
      LED_Off(num);
      Delay(450);                               /* Delay 450ms                */
    }
    else {
      LED_Out (0x0F);
      Delay(10);                                /* Delay 10ms                 */
    }
  }
  
}

效果和板子出厂时候自带的一样,因为这就是演示板自带的那个程序。
刚开始调用时钟初始化的子函数,然后检测是否配置正确,不正确了就进入while死循环,什么事情都不干。如果时钟配置好了,就初始化LED,初始化按钮。
接下来进入传说中的工作while死循环,先检测按键状态一下。并对按键进行统计,判断是否有再次按键行为,根据是否有再次按键行为作出两种不同的闪烁方法。
沙发
lvjing880907| | 2012-8-21 11:31 | 只看该作者
不错的帖子!值得学习

使用特权

评论回复
板凳
video_vb| | 2012-10-24 10:34 | 只看该作者
测试了那个转换成到内部时钟的函数,两个USART通讯正常.
RC的误差1%,9600的速率应该可以长时间使用吧,测试中.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1898

主题

15642

帖子

199

粉丝