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 #include /******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 速度100mGPIOD->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#include/******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 #ifdef MyDebug_with_USART3bool 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 速度100mGPIOD->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 #include 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--; } }





运行结果:











【stm32f407之MyDebugger(操作寄存器)】

    推荐阅读