基于keil编写STM32f103ze代码:当key1按下并抬起时,开始计时,然后进行8组AD采样,采样结束后计时结束,输出计时的时间
时间: 2024-05-04 17:21:02 浏览: 110
基于keil环境下,定时器中断测试
以下是基于Keil编写STM32F103ZE的代码,实现当KEY1按下并抬起时进行8组AD采样,然后输出计时的时间:
```c
#include "stm32f10x.h"
#include <stdio.h>
#define ADC1_DR_Address ((uint32_t)0x4001244C)
volatile uint16_t ADC_ConvertedValue[8] = {0}; //存储ADC采样后的值
volatile uint32_t TimingDelay = 0; //计时器
void delay_ms(uint32_t nTime); //毫秒级延时函数
void ADC1_Configuration(void); //ADC配置函数
void NVIC_Configuration(void); //NVIC配置函数
void TIM2_Configuration(void); //定时器TIM2配置函数
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIOA和复用功能时钟
GPIO_InitTypeDef GPIO_InitStructure;
//配置PA0为输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC1_Configuration(); //配置ADC1
NVIC_Configuration(); //配置NVIC
TIM2_Configuration(); //配置TIM2
while (1)
{
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == RESET) //检测KEY1是否按下
{
TimingDelay = 0; //计时器清零
TIM_Cmd(TIM2, ENABLE); //启动定时器
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == RESET); //等待KEY1抬起
TIM_Cmd(TIM2, DISABLE); //关闭定时器
printf("Time: %d ms\r\n", TimingDelay); //输出计时的时间
for(int i=0; i<8; i++)
{
printf("ADC%d: %d\r\n", i, ADC_ConvertedValue[i]); //输出ADC采样后的值
}
printf("\r\n");
}
}
}
void delay_ms(uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void ADC1_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); //使能ADC1和GPIOA时钟
//配置PA1,PA2,PA3,PA4,PA5,PA6,PA7为模拟输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_NbrOfChannel = 8; //采样通道数为8
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); //配置通道1采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5); //配置通道2采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5); //配置通道3采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_55Cycles5); //配置通道4采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_55Cycles5); //配置通道5采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 6, ADC_SampleTime_55Cycles5); //配置通道6采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 7, ADC_SampleTime_55Cycles5); //配置通道7采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 8, ADC_SampleTime_55Cycles5); //配置通道8采样时间
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_ResetCalibration(ADC1); //ADC1校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待校准结束
ADC_StartCalibration(ADC1); //ADC1开始校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //优先级分组为2
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; //ADC1, ADC2通道中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 1000 - 1; //计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; //预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式为向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //更新中断使能
}
void ADC1_2_IRQHandler(void)
{
if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET) //检测ADC转换是否完成
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); //清除ADC转换完成标志位
}
if(ADC_GetITStatus(ADC1, ADC_IT_EOSEQ) != RESET) //检测ADC序列转换是否完成
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOSEQ); //清除ADC序列转换完成标志位
for(int i=0; i<8; i++)
{
ADC_ConvertedValue[i] = ADC_GetConversionValue(ADC1); //将转换完成的值存储在数组中
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发ADC转换
}
}
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检测定时器TIM2是否更新
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除定时器TIM2更新标志位
if(TimingDelay > 0) TimingDelay--; //计时器减1
}
}
```
代码中使用了定时器TIM2和ADC1中断,当KEY1按下并抬起时,启动定时器计时,等待8组AD采样完成后停止计时并输出计时的时间和ADC采样后的值。注意,本代码仅供参考,需要根据具体情况进行修改和完善。
阅读全文