例程1的使用:
本例展示了如何采集单个通道的模拟输入,通过模数转换器(ADC)将模拟量转化为数据,并通过DMA把数据转移到内存中。
ADC工作在连续转换模式
//在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换
采集通道10(ADC Channel10)的输入在每次转换结束后由DMA把ADC_DR1寄存器内的转换结果传入ADC_ConvertedValue,然后把采集得到的数据,显示在液晶屏幕上。
//分压器连接在ADC channel10上
这样,PC.00管脚上的电压值,就直接显示在屏幕上了,0000对应0V,0FFF对应3.3V,调节分压器VR1,可以看到屏幕上的数值有相应的改变。
主程序:
int main(void)
{
#ifdef DEBUG // 在main 函数中必须包括这组语句
debug();
#endif
/* System clocks configuration ---------------------------------------------*/
RCC_Configuration(); //系统时钟配置
/* NVIC configuration ------------------------------------------------------*/
NVIC_Configuration(); //嵌套向量中断控制器(NVIC)配置
/* GPIO configuration ------------------------------------------------------*/
GPIO_Configuration(); //通用IO(GPIO)配置
/* Configure the systick */
SysTick_Config();
LcdShow_Init();
/* DMA channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA_Channel1); //DMA channel1 设置为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; // 定义DMA 外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//规定了外设是作为数据传输的来源
DMA_InitStructure.DMA_BufferSize = 1;//用以定义指定DMA通道的DMA缓存的大小,单位为数据单位。
根据传输方向,数据单位等于结构中参数DMA_PeripheralDataSize或者参数DMA_MemoryDataSize的值。
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//DMA_PeripheralInc用来设定外设地址寄存器递增与否
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//DMA_MemoryInc用来设定内存地址寄存器递增与否
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/*MA_PeripheralDataSize设定了外设数据宽度
DMA_PeripheralDataSize_Byte 数据宽度为8位
DMA_PeripheralDataSize_HalfWord 数据宽度为16位
DMA_PeripheralDataSize_Word 数据宽度为32位
*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/*DMA_MemoryDataSize设定了外设数据宽度*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*
DMA_Mode设置了CAN的工作模式
DMA_Mode_Circular 工作在循环缓存模式
DMA_Mode_Normal 工作在正常缓存模式
注意:当指定DMA通道数据传输配置为内存到内存时,不能使用循环缓存模式*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/*DMA_Priority设定DMA通道x的软件优先*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/*DMA_M2M失能DMA通道的内存到内存传输。*/
DMA_Init(DMA_Channel1, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA_channel1
/* Enable DMA channel1 */
DMA_Cmd(DMA_Channel1, ENABLE); //DMAchannel1使能
/* ADC1 configuration ---------------------------------ADC1 配置---------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
/*ADC_Mode设置ADC工作在独立或者双ADC模式 //ADC_Mode_Independent ADC1和ADC2工作在独立模式
ADC_Mode_Independent ADC1和ADC2工作在独立模式
ADC_Mode_RegInjecSimult ADC1和ADC2工作在同步规则和同步注入模式
ADC_Mode_RegSimult_AlterTrig ADC1和ADC2工作在同步规则模式和交替触发模式
ADC_Mode_InjecSimult_FastInterl ADC1和ADC2工作在同步规则模式和快速交替模式
ADC_Mode_InjecSimult_SlowInterl ADC1和ADC2工作在同步注入模式和慢速交替模式
ADC_Mode_InjecSimult ADC1和ADC2工作在同步注入模式
ADC_Mode_RegSimult ADC1和ADC2工作在同步规则模式
ADC_Mode_FastInterl ADC1和ADC2工作在快速交替模式
ADC_Mode_SlowInterl ADC1和ADC2工作在慢速交替模式
ADC_Mode_AlterTrig ADC1和ADC2工作在交替触发模式*/
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
//ADC_ScanConvMode规定了模数转换工作在扫描模式(多通道)还是单次(单通道)模式。
//可以设置这个参数为ENABLE或者DISABLE。
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//ADC_ContinuousConvMode规定了模数转换工作在连续模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC_ExternalTrigConv定义了使用外部触发来启动规则通道的模数转换
/*ADC_ExternalTrigConv_T1_CC1 选择定时器1的捕获比较1作为转换外部触发
ADC_ExternalTrigConv_T1_CC2 选择定时器1的捕获比较2作为转换外部触发
ADC_ExternalTrigConv_T1_CC3 选择定时器1的捕获比较3作为转换外部触发
ADC_ExternalTrigConv_T2_CC2 选择定时器2的捕获比较2作为转换外部触发
ADC_ExternalTrigConv_T3_TRGO 选择定时器3的TRGO作为转换外部触发
ADC_ExternalTrigConv_T4_CC4 选择定时器4的捕获比较4作为转换外部触发
ADC_ExternalTrigConv_Ext_IT11 选择外部中断线11事件作为转换外部触发
ADC_ExternalTrigConv_None 转换由软件而不是外部触发启动
*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//ADC_DataAlign规定了ADC数据向左边对齐还是向右边对齐。
ADC_InitStructure.ADC_NbrOfChannel = 1;
//ADC_NbreOfChannel 规定了顺序进行规则转换的ADC通道的数目。这个数目的取值范围是1到16。
ADC_Init(ADC1, &ADC_InitStructure);
//根据ADC_InitStruct中指定的参数初始化外设ADC1的寄存器
/* ADC1 regular channel10 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE); 使能ADC1的DMA请求
/* Enable ADC1
ADC_Cmd只能在其他ADC设置函数之后被调用。*/
ADC_Cmd(ADC1, ENABLE); 使能ADC1
/* Enable ADC1 reset calibaration register
重置指定的ADC的校准寄存器*/
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
//获取ADC重置校准寄存器的状态
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
//开始指定ADC的校准状态
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
//获取指定ADC的校准程序
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//使能或者失能指定的ADC的软件转换启动功能
#if 1
while(1) // LCD 显示部分
{
vu16 value = ADC_ConvertedValue;
u8 num1 = value&0xf;
u8 num2 = (value&0xff)>>4;
u8 num3= (value&0xfff)>>8;
u8 num4 = value>>12;
if (num1>9)
display[3]=num1+(65-10);
else
display[3]=num1+(48-0);
if (num2>9)
display[2]=num2+(65-10);
else
display[2]=num2+(48-0);
if (num3>9)
display[1]=num3+(65-10);
else
display[1]=num3+(48-0);
if (num4>9)
display[0]=num4+(65-10);
else
display[0]=num4+(48-0);
write_string(display);
delay();
}
#endif
}
LCD显示使用了TIM2的中断,因此调用函数LcdShow_Init()来做相应的初始化,在中断配置函数(NVIC_Configuration())中,授权来自TIM2的中断,在中断函数文件stm32f10x_it.c中,也要修改相应的TIM2_IRQHandler(void)。
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/*typedef struct
{
u8 NVIC_IRQChannel;
u8 NVIC_IRQChannelPreemptionPriority;
u8 NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
*/
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Set the Vector Table base location at 0x20000000
NVIC_VectTab:指定向量表位置在RAM还是在程序存储器
Offset:向量表基地址的偏移量
对FLASH,该参数值必须高于0x08000100;
对RAM必须高于0x100。
它同时必须是256(64×4)的整数倍*/
/* Configure the Priority Group to 2 bits
设置优先级分组:先占优先级和从优先级
NVIC_PriorityGroup_0先占优先级0位 从优先级4位
NVIC_PriorityGroup_1先占优先级1位 从优先级3位
NVIC_PriorityGroup_2 先占优先级2位 从优先级2位
NVIC_PriorityGroup_3先占优先级3位 从优先级1位
NVIC_PriorityGroup_4先占优先级4位 从优先级0位*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* enabling interrupt */
NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel;
//该参数用以使能或者失能指定的IRQ通道
//USB低优先级或者CAN接收0中断 。这部分我也不明白原因。
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//该参数设置了成员NVIC_IRQChannel中的先占优先级
//先占优先级0位 从优先级4位
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//该参数设置了成员NVIC_IRQChannel中的从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//该参数指定了在成员NVIC_IRQChannel中定义的IRQ通道被使能。
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
/* enabling interrupt */
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure the SysTick handler priority */
NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 2, 0);
}//设置指定的系统Handler优先级
/*SystemHandler_MemoryManage 存储器管理Handler
SystemHandler_BusFault 总线错误Handler
SystemHandler_UsageFault使用错误Handler
SystemHandler_SVCall SVCall Handler
SystemHandler_DebugMonitor 除错监控Handler
SystemHandler_PSV PSV Handler
SystemHandler_SysTick 系统滴答定时器Handler
*/