stm32f407之MyDebugger(操作寄存器)

九、MyDebugger

         已经学习了usart和DMA,因为后面的学习,最好有一个直观点的人性化的显示终端。可以通过串口将数据和文字信息发送往电脑,然后在上位机软件上观察数据以及调试信息。为此,我写了一个文件,以供日后调试之用,命名为MyDebugger。

         首先,参照之前的程序,略加修改,将USART的接收功能全部去掉,DMA的配置分开,独立写成一个配置DMA的函数USART3_DMA_config(),把发送的部分写到MyDebugger_Message(char *str_address, unsigned int str_len)函数内,很简单地实现了一个发送字符消息的函数。然后写一个操作板子上指示灯的函数,用以日后指示调试信息。具体的实现,请看下程序(实现MyDebugger的验证程序)。

         把验证程序分离写成头文件形式。方便以后其他工程使用。把程序稍作修改,利用条件编译,为以后可能的添加其他通信方式提供方便。要使用USART3作为调试通信方式,必须先定义宏MyDebug_with_USART3,如下图所示:


实现MyDebugger的验证程序:

/*********************************************
    标题:MyDebugger
    软件平台:IAR for ARM6.21
    硬件平台:stm32f4-discovery
    主频:168M
    
    描述:实现一个调试工具
          
    author:小船
    data:2012-02-04
**********************************************/
#include <stm32f4xx.h> 
#include <stdbool.h>

/******LED宏定义*******/
#define green 0x00001000
#define orange 0x00002000
#define red 0x00004000
#define blue 0x00008000

/******全局变量及类型声明*******/
bool USART_DMA_Completed;
enum LED_State {on, off, turn};

/******函数声明*******/
void LEDs_Init(void);
void USART3_DMA_config(void);
void USART3_config(void);
bool MyDebugger_Message(char *str_address, unsigned int str_len);
void MyDebugger_LEDs(uint32_t LED, enum LED_State state);

void main ()
{ 
  SysTick_Config(SystemCoreClock / 1000); //设置systemtick一毫秒中断
  SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1
  LEDs_Init();
  USART3_DMA_config();
  USART3_config();
  
  USART_DMA_Completed = 1;
  
  while(1)
  { 
    MyDebugger_Message("My name is Xian Yongwen\n", 
                            sizeof("My name is Xian Yongwen\n")/sizeof(char));
    
    MyDebugger_Message("广东石油化工学院\n", 
                            sizeof("广东石油化工学院\n")/sizeof(char));
  }
}

/*********************************************
  函数名:MyDebugger_Message
  参数:char *str_address  :要发送的字符串地址
        unsigned int str_len  :字符串的长度
  返回值:bool  是否操作成功
  功能:通过USART3发送信息
**********************************************/
bool MyDebugger_Message(char *str_address, unsigned int str_len)
{ 
    if( USART_DMA_Completed )  //之前数据已经发送完成
    {  
      DMA1_Stream3->CR &= 0xFFFFFFFE;   //除能DMA1_Stream3
      while(DMA1_Stream3->CR & 0x00000001); //确保DMA可以被设置     
      DMA1->LIFCR |= 0x0f800000;  //传送前清空DMA1_Stream3所有中断标志  
      DMA1_Stream3->M0AR = (uint32_t)str_address; //设置内存地址
      if((USART3->SR & (1<<7))) //发送数据寄存器空
      {
        USART3->CR3 &= ~(1<<7);//usart3 dma发送模式除能
        USART_DMA_Completed = 0;
        DMA1_Stream3->NDTR = str_len; //设置dma传输数据的数量
        DMA1_Stream3->CR |= 1;//使能dma
        USART3->CR3 |= (1<<7);//usart3 dma发送模式使能
        return true;
      } 
    } 
    return false;
}

/****************************************
  函数名:MyDebugger_LEDs
  参数:uint32_t LED  :要操作哪些LED
        enum LED_State state  :作何操作
  返回值:无
  功能:改变LED的状态
****************************************/
void MyDebugger_LEDs(uint32_t LED, enum LED_State state)
{
  uint32_t tmp;
  switch (state)
  {
    case on:
      {
        GPIOD->BSRRL |= LED; 
        break;
      }
    case off:
      {
        GPIOD->BSRRH |= LED;
        break;
      }
    case turn:
      {
        tmp = (~GPIOD->ODR) & LED;   
        GPIOD->ODR &= ~LED;
        GPIOD->ODR |= tmp;
        break;
      } 
  }
}

/****************************************
  函数名:USART3_DMA_config
  参数:无
  返回值:无
  功能:DMA1数据流3与usart3关联的相关配置
****************************************/
void USART3_DMA_config(void)
{
  RCC->AHB1ENR |= (1<<21); //使能DMA1时钟
  DMA1_Stream3->CR &= 0xFFFFFFFE; //除能DMA1_Stream3
  while(DMA1_Stream3->CR & 0x00000001);//确保DMA可以被设置
  
  DMA1->LIFCR |= 0x0f800000;//传送前清空DMA1_Stream3所有中断标志
  
  DMA1_Stream3->PAR = (uint32_t)&USART3->DR;//设置外设地址USART3->DR地址0x40004804
                                             //设置内存地址
  DMA1_Stream3->FCR &= 0x00000000;
  DMA1_Stream3->FCR |= (1<<7);//设置fifo
  /*
    设置dma通道4,即usart3tx
    优先级最高
    传输方向内存到外设
    内存递增模式
    传输完成中断使能
  */
  DMA1_Stream3->CR |= (0x08000000 | 0x00030000 | (1<<6)
                       | (1<<10) | (1<<4) | (1<<2)|(1<<1)); 
  
  NVIC->IP[14] = 0xA0;
  NVIC->ISER[0] |= (1<<14);
  
}

/**************************
  函数名:USART3_config
  参数:无
  返回值:无
  功能:配置usart3
************************/
void USART3_config(void)
{
  RCC->APB1ENR |= (1<<18);  //使能usart3时钟
  RCC->AHB1ENR |= 0x00000008; //使能GPIOD时钟
  USART3->BRR = 0x0000016C;   //波特率115200
  /*
   使能usart3
  usart3发送使能
  8bit
  一位停止位
  无校验
  */
  USART3->CR1 |= ( ( 1<<13 ) | ( 1<<3 ) ); 
  
  GPIOD->AFR[1] |= 0x00000077;//选择PD8,9复用功能 
  
  GPIOD->MODER &= 0xFFF0FFFF; //设置PD8,9,复用模式
  GPIOD->MODER |= 0x000A0000; 
    
  GPIOD->OSPEEDR &= 0xFFFCFFFF; //PD8速度50m
  GPIOD->OSPEEDR |= 0x00020000;
  
  GPIOD->PUPDR &= 0xFFFCFFFF; //PD8
  GPIOD->PUPDR |= 0x00010000;
}

/****************************************
  函数名:LEDs_Init
  参数:无
  返回值:无
  功能:初始化板子上的LED
****************************************/
void LEDs_Init(void)
{
  RCC->AHB1ENR |= 0x00000008; //使能GPIOD时钟
  
  GPIOD->MODER &= 0x00FFFFFF; //设置PD12,13,14,15输出
  GPIOD->MODER |= 0x55000000; 
  
  GPIOD->OTYPER &= 0xFFFF0FFF; //设置PD12,13,14,15推挽输出
  
  GPIOD->OSPEEDR &= 0x00FFFFFF; //PD12,13,14,15 速度100m
  
  GPIOD->PUPDR &= 0x00FFFFFF;  //PD12,13,14,15 无上拉无下拉
  
  GPIOD->BSRRH = 0xf000;  //reset register GPIOx_BSRRH, write only
                          //set register GPIOx_BSRRL, write only
}

void DMA1_Stream3_IRQHandler(void)
{
  if(DMA1->LISR & 0x08000000)//DMA传输完成
  {
    USART_DMA_Completed = 1;
    DMA1->LIFCR |= 0x08000000;//清除中断标志
  }
  if(DMA1->LISR & 0x03000000)     //如果发生传输错误或直接模式错误,亮橙色LED
  {
    MyDebugger_LEDs( orange, on);
    DMA1->LIFCR |= 0x03000000;
  }
  if(DMA1->LISR & (1<<22))  //如果发生fifo错误,亮红色指示灯
  {
    MyDebugger_LEDs( red, on);
    DMA1->LIFCR |= (1<<22);
  }
}

实用程序:

头文件:MyDebugger.h

// file:MyDebugger.h

#ifndef __MyDebugger_H #define __MyDebugger_H #include <stm32f4xx.h> #include <stdbool.h> /******LED宏定义*******/ #define green 0x00001000 #define orange 0x00002000 #define red 0x00004000 #define blue 0x00008000 /******全局变量及类型声明*******/ enum LED_State {on, off, turn}; /******函数声明*******/ void MyDebugger_Init(void); bool MyDebugger_Message(char *str_address, unsigned int str_len); void MyDebugger_LEDs(uint32_t LED, enum LED_State state); #endif

源文件:MyDebugger.c

// file:MyDebugger.c
#include <MyDebugger.h> 

#ifdef MyDebug_with_USART3

bool USART_DMA_Completed = true;

/****************************************
  函数名:USART3_DMA_config
  参数:无
  返回值:无
  功能:DMA1数据流3与usart3关联的相关配置
****************************************/
void USART3_DMA_config(void)
{
  RCC->AHB1ENR |= (1<<21); //使能DMA1时钟
  DMA1_Stream3->CR &= 0xFFFFFFFE; //除能DMA1_Stream3
  while(DMA1_Stream3->CR & 0x00000001);//确保DMA可以被设置
  
  DMA1->LIFCR |= 0x0f800000;//传送前清空DMA1_Stream3所有中断标志
  
  DMA1_Stream3->PAR = (uint32_t)&USART3->DR;//设置外设地址USART3->DR地址0x40004804
                                             //设置内存地址
  DMA1_Stream3->FCR &= 0x00000000;
  DMA1_Stream3->FCR |= (1<<7);//设置fifo
  /*
    设置dma通道4,即usart3tx
    优先级最高
    传输方向内存到外设
    内存递增模式
    传输完成中断使能
  */
  DMA1_Stream3->CR |= (0x08000000 | 0x00030000 | 
                        (1<<6) | (1<<10) | (1<<4)); 
  
  NVIC->IP[14] = 0xA0;
  NVIC->ISER[0] |= (1<<14);
}

/**************************
  函数名:USART3_config
  参数:无
  返回值:无
  功能:配置usart3
************************/
void USART3_config(void)
{
  RCC->APB1ENR |= (1<<18);  //使能usart3时钟
  RCC->AHB1ENR |= 0x00000008; //使能GPIOD时钟
  USART3->BRR = 0x0000016C;   //波特率115200
  /*
   使能usart3
  usart3发送使能
  8bit
  一位停止位
  无校验
  */
  USART3->CR1 |= ( ( 1<<13 ) | ( 1<<3 ) ); 
  
  GPIOD->AFR[1] |= 0x00000077;//选择PD8,9复用功能 
  
  GPIOD->MODER &= 0xFFF0FFFF; //设置PD8,9,复用模式
  GPIOD->MODER |= 0x000A0000; 
  
//  GPIOD->OTYPER &= 0xFFFFDFFF; //设置PD9推挽输出
  
  GPIOD->OSPEEDR &= 0xFFFCFFFF; //PD8速度50m
  GPIOD->OSPEEDR |= 0x00020000;
  
  GPIOD->PUPDR &= 0xFFFCFFFF; //PD8
  GPIOD->PUPDR |= 0x00010000;
}

void DMA1_Stream3_IRQHandler(void)
{
  if(DMA1->LISR & 0x08000000)//DMA传输完成
  {
    USART_DMA_Completed = 1;
    DMA1->LIFCR |= 0x08000000;//清除中断标志
  }
}
#endif

/*********************************************
  函数名:MyDebugger_Message
  参数:char *str_address  :要发送的字符串地址
        unsigned int str_len  :字符串的长度
  返回值:bool  是否操作成功
  功能:通过USART3发送信息
**********************************************/
bool MyDebugger_Message(char *str_address, unsigned int str_len)
{   
#ifdef MyDebug_with_USB
    bool USB_Actioned;
#endif
    
#ifdef MyDebug_with_USART3
    bool USART3_Actioned;
    if( USART_DMA_Completed )  //之前数据已经发送完成
    {  
      DMA1_Stream3->CR &= 0xFFFFFFFE;   //除能DMA1_Stream3
      while(DMA1_Stream3->CR & 0x00000001); //确保DMA可以被设置     
      DMA1->LIFCR |= 0x0f800000;  //传送前清空DMA1_Stream3所有中断标志  
      DMA1_Stream3->M0AR = (uint32_t)str_address; //设置内存地址
      if((USART3->SR & (1<<7))) //发送数据寄存器空
      {
        USART3->CR3 &= ~(1<<7);//usart3 dma发送模式除能
        USART_DMA_Completed = 0;
        DMA1_Stream3->NDTR = str_len; //设置dma传输数据的数量
        DMA1_Stream3->CR |= 1;//使能dma
        USART3->CR3 |= (1<<7);//usart3 dma发送模式使能
        USART3_Actioned = 1;
      } 
    }
#endif
    
#ifdef MyDebug_with_USB
//以后或许实现用USB发送调试信息的代码
    
       //如果操作USB成功
        USB_Actioned = 1;
#endif

#ifdef MyDebug_with_USART3
  #ifndef MyDebug_with_USB    
    return USART3_Actioned;
  #endif  
#endif

#ifdef MyDebug_with_USB
  #ifndef MyDebug_with_USART3    
    return USB_Actioned;
  #endif  
#endif

#ifdef MyDebug_with_USART3
  #ifdef MyDebug_with_USB    
    return (USART3_Actioned | USB_Actioned);
  #endif
#endif    
}

/****************************************
  函数名:LEDs_Init
  参数:无
  返回值:无
  功能:初始化板子上的LED
****************************************/
void LEDs_Init(void)
{
  RCC->AHB1ENR |= 0x00000008; //使能GPIOD时钟
  
  GPIOD->MODER &= 0x00FFFFFF; //设置PD12,13,14,15输出
  GPIOD->MODER |= 0x55000000; 
  
  GPIOD->OTYPER &= 0xFFFF0FFF; //设置PD12,13,14,15推挽输出
  
  GPIOD->OSPEEDR &= 0x00FFFFFF; //PD12,13,14,15 速度100m
  
  GPIOD->PUPDR &= 0x00FFFFFF;  //PD12,13,14,15 无上拉无下拉
  
  GPIOD->BSRRH = 0xf000;  //reset register GPIOx_BSRRH, write only
                          //set register GPIOx_BSRRL, write only
}

/****************************************
  函数名:MyDebugger_LEDs
  参数:uint32_t LED  :要操作哪些LED
        enum LED_State state  :作何操作
  返回值:无
  功能:改变LED的状态
****************************************/
void MyDebugger_LEDs(uint32_t LED, enum LED_State state)
{
  uint32_t tmp;
  switch (state)
  {
    case on:
      {
        GPIOD->BSRRL |= LED; 
        break;
      }
    case off:
      {
        GPIOD->BSRRH |= LED;
        break;
      }
    case turn:
      {
        tmp = (~GPIOD->ODR) & LED;   
        GPIOD->ODR &= ~LED;
        GPIOD->ODR |= tmp;
        break;
      } 
  }
}

/*********************************************
  函数名:MyDebugger_Init
  参数:无
  返回值:无
  功能:初始化MyDebugger
**********************************************/
void MyDebugger_Init(void)
{
  LEDs_Init();
  
#ifdef MyDebug_with_USART3
  USART3_DMA_config();
  USART3_config();
#endif
}



主程序文件:main.c

/*********************************************
    标题:MyDebugger
    软件平台:IAR for ARM6.21
    硬件平台:stm32f4-discovery
    主频:168M
    
    描述:实现一个调试工具
          
    author:小船
    data:2012-02-04
**********************************************/
#include <stm32f4xx.h> 
#include <MyDebugger.h> 

uint32_t Gb_TimingDelay;

void Delay(uint32_t nTime);

void main ()
{ 
  SysTick_Config(SystemCoreClock / 1000); //设置systemtick一毫秒中断
  //char test[15] = {0, 1, 2, 3, 4,  10, 11, 12, 13, 14, 15, 0xfe, 0xf0, 0x07, 0x09};
  SCB->AIRCR = 0x05AF0000 | 0x400;  //中断优先级分组 抢占:响应=3:1
  MyDebugger_Init();
  while(1)
  { 
    MyDebugger_Message("My name is Xian Yongwen\n\r", 
                            sizeof("My name is Xian Yongwen\n\r")/sizeof(char));
    
    MyDebugger_LEDs(blue, on);
    Delay(500);
    
    MyDebugger_Message("广东石油化工学院\n\r", 
                            sizeof("广东石油化工学院\n\r")/sizeof(char));
    
    MyDebugger_LEDs(blue, off);
    Delay(500);
  }
}

void Delay(uint32_t nTime)
{ 
  Gb_TimingDelay = nTime;

  while(Gb_TimingDelay != 0);
}

void SysTick_Handler(void)
{
  if (Gb_TimingDelay != 0x00)
  { 
    Gb_TimingDelay--;
  }
}



运行结果:









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章