原创 [原创]STM32 RVMDK学习实例_2. ADC&DMA&USART

2008-7-18 20:13 5472 8 14 分类: MCU/ 嵌入式

上文:STM32 RVMDK学习实例第一篇


http://blog.ednchina.com/liongt/134672/message.aspx


 


       STM32 RVMDK学习实例第二篇,用STM32ADC采集模拟电压,转换结果以DMA方式传输给USARTUSART通过串口发送到上位机。实验方法是先用RVMDK进行软件仿真,然后下载到开发板进行验证,所用的开发板是万利的EK-STM<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />32F


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


/* Includes ------------------------------------------------------------------*/


#include "main.h"


/* Private typedef -----------------------------------------------------------*/


/* Private define ------------------------------------------------------------*/


#define ADC1_DR_Address    ((u32)0x4001244C)


/* Private macro -------------------------------------------------------------*/


/* Private variables ---------------------------------------------------------*/


vu16 ADC_ConvertedValue;


/* Private function prototypes -----------------------------------------------*/


void RCC_Configuration(void);


void GPIO_Configuration(void);


void USART_Config(void);


void DMA_Config(void);


void ADC_Config(void);


void Delay(vu32 nCount);


 


/* Private functions ---------------------------------------------------------*/


/******************************************************************************


* Function Name  : main


* Description    : Main program


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


int main(void)


{


#ifdef DEBUG


       debug();


#endif


      


       RCC_Configuration();


       GPIO_Configuration();


       USART_Config();


       DMA_Config();


       ADC_Config();


 


       while (1)


       {


              Delay(0xFFFFFF); 


              printf("ADC = %X Volt = %d mv\r\n", ADC_ConvertedValue, ADC_ConvertedValue*3300/4096);


       }


}


 


/******************************************************************************


* Function Name  : RCC_Configuration


* Description    : Configures the different system clocks.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void RCC_Configuration(void)


{


       ErrorStatus HSEStartUpStatus; //定义外部高速晶体启动状态枚举变量


       RCC_DeInit(); //复位RCC外部设备寄存器到默认值


       RCC_HSEConfig(RCC_HSE_ON); //打开外部高速晶振


       HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速时钟准备好


       if(HSEStartUpStatus == SUCCESS) //外部高速时钟已经准备好


       {


              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


              FLASH_SetLatency(FLASH_Latency_2);


             


              RCC_HCLKConfig(RCC_SYSCLK_Div1); //配置AHB(HCLK)时钟==SYSCLK


              RCC_PCLK2Config(RCC_HCLK_Div1); //配置APB2(PCLK2)==AHB时钟


              RCC_PCLK1Config(RCC_HCLK_Div2); //配置APB1(PCLK1)==AHB1/2时钟


              RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);


              RCC_PLLCmd(ENABLE); //使能PLL时钟


      


              //等待PLL时钟就绪


              while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)


              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //配置系统时钟 = PLL时钟


              //等待PLL时钟作为系统时钟


              while(RCC_GetSYSCLKSource() != 0x08)


       }


       /* Enable DMA clock */


      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);


 


      /* Enable ADC1 and GPIOC clock */


       RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);


 


    //打开GPIOAFIO时钟


       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx | RCC_APB2Periph_AFIO, ENABLE);


      


       //使能串口时钟


#ifdef USE_USART1 


       RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


#else


       RCC_APB1PeriphClockCmd(RCC_APB1Periph_USARTx, ENABLE);


#endif


}


 


/******************************************************************************


* Function Name  : GPIO_Configuration


* Description    : Configures the different GPIO ports.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void GPIO_Configuration(void)


{


       GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体


      


#ifdef USE_USART2


       /* Enable the USART2 Pins Software Remapping */


       GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); //使能GPIO端口映射USART2


#endif


 


       // For STM3210B-LK1 configure PC.00 (ADC Channel10)


      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;


      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;


      GPIO_Init(GPIOC, &GPIO_InitStructure);


 


       /* Configure USARTx_Tx as alternate function push-pull */


       GPIO_InitStructure.GPIO_Pin = GPIO_TxPin;


       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚频率50M


       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;


       GPIO_Init(GPIOx, &GPIO_InitStructure);


      


       /* Configure USARTx_Rx as input floating */


       GPIO_InitStructure.GPIO_Pin = GPIO_RxPin;


       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置Rx引脚为浮点输入模式


       GPIO_Init(GPIOx, &GPIO_InitStructure);


      


}


 


/******************************************************************************


* Function Name  : USART_Config(void);


* Description    : Configures the USART ports.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void USART_Config(void)


{


       USART_InitTypeDef USART_InitStructure; //定义串口初始化结构体


       USART_InitStructure.USART_BaudRate = 115200; //波特率115200


       USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据


       USART_InitStructure.USART_StopBits = USART_StopBits_1; //1个停止位


       USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位


       USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //禁用RTSCTS硬件流控制


       USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使能接收/发送


       USART_InitStructure.USART_Clock = USART_Clock_Disable; //串口时钟禁止


       USART_InitStructure.USART_CPOL = USART_CPOL_Low; //时钟下降沿有效


       USART_InitStructure.USART_CPHA = USART_CPHA_2Edge; //数据在第二个时钟沿捕捉


       USART_InitStructure.USART_LastBit = USART_LastBit_Disable; //最后数据位的时钟脉冲不输出到SCLK引脚


      


       USART_Init(USARTx, &USART_InitStructure); //初始化串口(USARTxmain.h中定义)


       USART_Cmd(USARTx, ENABLE); //串口使能


}


 


/******************************************************************************


* Function Name  : PUTCHAR_PROTOTYPE


* Description    : Retargets the C library printf function to the USART.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


PUTCHAR_PROTOTYPE


{


       /* Write a character to the USART */


       USART_SendData(USARTx, (u8) ch);


      


       /* Loop until the end of transmission */


       while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)


       {


       }


      


       return ch;


}


/******************************************************************************


* Function Name  : DMA_Config(void);


* Description    : Configures the DMA.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void DMA_Config(void)


{


       DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体


       DMA_DeInit(DMA_Channel1);//复位DMA通道1


       DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义 DMA通道外设基地址=ADC1_DR_Address


       DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //定义DMA通道存储器地址


       DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设为源地址


       DMA_InitStructure.DMA_BufferSize = 1;//定义DMA缓冲区大小1


       DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变


       DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//当前存储器地址不变


       DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16


       DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16


       DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA通道操作模式位环形缓冲模式


       DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高


       DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止DMA通道存储器到存储器传输


       DMA_Init(DMA_Channel1, &DMA_InitStructure);//初始化DMA通道1


       DMA_Cmd(DMA_Channel1, ENABLE); //使能DMA通道1


}


 


/******************************************************************************


* Function Name  : ADC_Config(void);


* Description    : Configures the ADC.


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void ADC_Config(void)


{


       ADC_InitTypeDef ADC_InitStructure;//定义ADC初始化结构体变量


       ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC1ADC2工作在独立模式


       ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描


       ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ADC转换工作在连续模式


       ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//有软件控制转换


       ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换数据右对齐


       ADC_InitStructure.ADC_NbrOfChannel = 1;//转换通道为通道1


       ADC_Init(ADC1, &ADC_InitStructure); //初始化ADC


       ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);


       //ADC1选择通道10


ADC_DMACmd(ADC1, ENABLE);//使能ADC1模块DMA


       ADC_Cmd(ADC1, ENABLE);//使能ADC1


       ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器


       //等待ADC1校准重置完成


       while(ADC_GetResetCalibrationStatus(ADC1));


       ADC_StartCalibration(ADC1);//开始ADC1校准


       //等待ADC1校准完成


       while(ADC_GetCalibrationStatus(ADC1));


       ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件开始转换


}


 


/******************************************************************************


* Function Name  : Delay() ;


* Description    : None


* Input          : None


* Output         : None


* Return         : None


*******************************************************************************


void Delay(vu32 nCount)


{


       while(nCount--);


}


 


#ifdef  DEBUG


/******************************************************************************


* Function Name  : assert_failed


* Description    : Reports the name of the source file and the source line number


*                  where the assert_param error has occurred.


* Input          : - file: pointer to the source file name


*                  - line: assert_param error line source number


* Output         : None


* Return         : None


*******************************************************************************


void assert_failed(u8* file, u32 line)


{


/* User can add his own implementation to report the file name and line number,


ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */


      


       /* Infinite loop */


       while (1)


       {


       }


}


#endif


 


       进行软件仿真时,先要选择Debug工具为“Use Simulator ,然后进入Debug模式。在Peripheral菜单中选择ADC1,打开ADC1仿真对话框,并在Analog InputsADC1_IN10一栏中输入模拟电压输入值。


 

 


点击看大图


      


       接下来在Peripheral菜单中选择USART1,打开串口仿真窗口。最后点击Debug工具条的运行按钮,即可在USART1仿真窗口中看到采集到的模拟电压值了。



a00ffc7f-f94e-4c35-ac3b-f39e9f072ee3.jpg


      


       在万利的EK-STM32开发板上运行时,只需选择Debug工具为“ST Link-II ,然后将程序下载到开发板,用串口线将开发板上的USART1和电脑相连,即可在串口调试助手中收到模拟电压值了,旋转开发板上的电位器可以调节输入的模拟电压。


 


       好了,今天很累了,先到这里,祝大家实验成功!


 

PARTNER CONTENT

文章评论6条评论)

登录后参与讨论

用户208051 2012-11-21 10:58

正好需要呢

用户506238 2008-11-28 16:26

既然用到ADC,怎么没有调用RCC_ADCCLKConfig来设置ADC时钟? PLL倍频系数RCC_PLLMul_9无法实现,,调试的时候一直停在 while(RCC_GetSYSCLKSource()!= 0x08) 状态,换成RCC_PLLMul_7就可以了

用户506238 2008-11-28 16:13

既然用到ADC,怎么没有调用RCC_ADCCLKConfig来设置ADC时钟? PLL倍频系数RCC_PLLMul_9无法实现,,调试的时候一直停在 while(RCC_GetSYSCLKSource()!= 0x08) 状态,换成RCC_PLLMul_7就可以了

用户506238 2008-11-28 12:05

/* Private define ------------------------------------------------------------*/ #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ 我在代码里加了上述代码,编译才通过。 但是软件仿真时在UART#1没有输出,是不是哪里设置不对?请教了.

用户1560991 2008-7-23 15:30

ST Link-II无法使用Download功能,MDK评估版不支持,用Debug下载程序。

用户158184 2008-7-22 15:42

学习,期待继续发帖!

用户1113894 2008-7-21 16:41

帮个忙,我用 RVMDK 怎么无法 download,显示“This function is limitied”? QQ:3543031

用户703457 2008-1-31 09:50

好东西!!!!!!!!!!!!!!!!!!!!!

相关推荐阅读
用户1560991 2008-12-10 19:55
最简单的C#入门教程
从网上找到的C#学习的好资料! 关于作者:Aisha Ikram        我现在在英国一家软件公司任技术带头人。我是计算机科学的硕士。我主要使用 .NET 1.1/2.0, C#, VB.NET...
用户1560991 2008-12-08 22:40
在C#中加载自己编写的动态链接库(转贴)
        本文主要讲述如何在C#中逐步实现加载自己用C++语言编写的动态链接库,以及在导入时如何进行C#和C++语言的数据类型匹配。 一、发生的背景         在开发新项目中使用了新的语言...
用户1560991 2008-12-08 10:25
新的学习方向
        最近的生活总算恢复正常了,可以静下心来学点东西了!新的学习方向是VC#,以前俺用的是VC++ 6.0,最近看到同学在用VC# 2005,很好很强大,支持快速开发。于是俺就想学学,以后用...
用户1560991 2008-08-08 11:04
基于STM32和nRF905的无线数传系统_软件篇
              STM32与nRF905模块间的电路连好后,剩下的工作就是编写程序了。都说STM32的固件库难用,但俺觉得从中可以学到不少东西,尤其是模块化编程的思想。STM32的固件库将...
用户1560991 2008-08-05 12:58
基于STM32和nRF905的无线数传系统_硬件篇
最近搞到一对nRF905无线模块,迫不及待的拿出来给大伙瞧瞧。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:...
用户1560991 2008-08-03 20:31
STM32精确延时的实现方法
前面用STM32的GPIO模拟液晶驱动时序时遇到一个问题,就是怎样产生一段较为精确的延时。通常产生一小段延时的方法就是利用一个递增或者递减循环进行软件延时。<?xml:namespace pre...
EE直播间
更多
我要评论
6
8
关闭 站长推荐上一条 /3 下一条