新手上路
- 积分
- 34
- 金钱
- 34
- 注册时间
- 2015-1-8
- 在线时间
- 0 小时
|
5金钱
现在做项目遇到一个问题,望各位指点一二:多谢多谢!
stm32f103 adc采样 sd卡存储
单通道,40ksps,每秒80KB的数据,开启了timer1 触发adc的中断,利用dma将adc的数据先存到一个10KB*2的数组;
然后在dma中断中 将数据存入sd卡中,每次采集10s(每个文件,800kB),发现有的文件会出现数据错误的现象,有的文件正常。
程序如下:
timer1的配置:
/* TIM1 configuration ------------------------------------------------------*/
/* Time Base configuration */
//中断的频率 = 8M(外接晶振频率)*9(PLL系数)/(分频系数)/(1+预分频系数)/ARR
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = 1800;//2000;// 36ksps 2250;//32k sps ;10*180;//40k 720--100k 1440/2--50k
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1800/2;//5*180;// 5*180;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Enable TIM1 */
//TIM_Cmd(TIM1, ENABLE);
/* Enable TIM1 outputs */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
adc的配置:
ADC_DeInit(ADC1);//adc rest 一次
//ADC配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC1工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//ENABLE; //模数转换工作在扫描模式(多通道)还是单次(单通道)模式
//en--多通道
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ENABLE; //
//连续采样模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//2;//3 //规定了顺序进行规则转换的ADC通道的数目。这个数目的取值范围是1到16
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration [规则模式通道配置]*/
//ADC1 规则通道配置
//ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_7Cycles5); //通道11采样时间 55.5周期
//ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_7Cycles5); //通道11采样时间 55.5周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_239Cycles5); //通道11采样时间 55.5周期
//ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 2, ADC_SampleTime_7Cycles5); //通道11采样时间 55.5周期
//使能ADC1 DMA
ADC_DMACmd(ADC1, ENABLE);
//使能ADC1
ADC_Cmd(ADC1, ENABLE);
// 初始化ADC1校准寄存器
ADC_ResetCalibration(ADC1);
//检测ADC1校准寄存器初始化是否完成
while(ADC_GetResetCalibrationStatus(ADC1));
//开始校准ADC1
ADC_StartCalibration(ADC1);
//检测是否完成校准
while(ADC_GetCalibrationStatus(ADC1));
//ADC1转换启动
//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_ExternalTrigConvCmd(ADC1, ENABLE); //设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,实际上还是在STM32内部)
dma的配置:
/* DMA channel1 configuration ----------------------------------------------*/
//使能DMA
DMA_DeInit(DMA1_Channel1); // DMA通道1硬件就是专供ADC1的
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA通道1的地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //DMA传送地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //传送方向
DMA_InitStructure.DMA_BufferSize = max_dma_size;//2*max_dma_size;//2通道*1024 //传送内存大小,3个16位
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //传送内存地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //ADC1转换的数据是16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //传送的目的地址是16位宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* 允许DMA1通道1传输结束中断 */
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);
/* 允许DMA1通道1半传输结束中断 */
DMA_ITConfig(DMA1_Channel1,DMA_IT_HT, ENABLE);
dma中断服务子程序:
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_FLAG_HT1)!=RESET) //判断通道1半传输完成
{
DMA_ClearFlag(DMA1_FLAG_HT1);//清除通道1半传输完成标志
//LED0_ON;
if(ad_file_wr_en==1)
{
for(cnt_ads=0;cnt_ads<max_dma_size/2;cnt_ads++)
{
temp0=ADC_ConvertedValue[cnt_ads];
buffer_ad_sd1[0+(cnt_ads<<1)]=temp0>>8;//H--8bit
buffer_ad_sd1[1+(cnt_ads<<1)]=temp0&0x00ff;//L--8bit
}
LED0_ON;
for(i_dma=0;i_dma<max_dma_size/512;i_dma++)
{
res2 = f_write(&fdst,&buffer_ad_sd1[512*i_dma],512, &bw2);//512 如果大于512则会写入出错
}
LED0_OFF;
}
}
else if(DMA_GetFlagStatus(DMA1_FLAG_TC1)!=RESET) //判断通道1传输完成
{
DMA_ClearFlag(DMA1_FLAG_TC1);//清除通道1传输完成标志
//LED0_OFF;
if(ad_file_wr_en==1)
{
for(cnt_ads=0;cnt_ads<max_dma_size/2;cnt_ads++)
{
temp0=ADC_ConvertedValue[cnt_ads+max_dma_size/2];
buffer_ad_sd1[0+(cnt_ads<<1)]=temp0>>8;//H--8bit
buffer_ad_sd1[1+(cnt_ads<<1)]=temp0&0x00ff;//L--8bit
}
LED0_ON;
for(i_dma=0;i_dma<max_dma_size/512;i_dma++)
{
res2 = f_write(&fdst,&buffer_ad_sd1[512*i_dma],512, &bw2);//512 如果大于512则会写入出错
}
LED0_OFF;
}
}
//
if(wdt_feed_en==1)
WatchDog_Feed();
//
if(ad_file_wr_en)
{
//if(cnt_dma==(40*1024*2/max_dma_size-1))//40k/8k
if(cnt_dma==(16-1))//
{
cnt_dma=0;
flag_dma_1s=1;
if(flag_dma_1s)
{
flag_dma_1s=0;
cnt_1s_wrsd++;
//
w_LCD_Show_num(239-0,29*8,cnt_1s_wrsd);//显示0-65535 十进制 字模 16*8
//
if(cnt_1s_wrsd==samp_s)//默认10s 范围: 2-20s
{
cnt_1s_wrsd=0;
ad_file_wr_en=0;
//TIM_Cmd(TIM1,DISABLE);//关闭 timer1
file_wr_finish=1;
f_close(&fdst);
}
}
}
else
{
cnt_dma++;
}
}
}
|
|