为什么我的DMA+ADCmatlab读取图像灰度值到值一直是初始值

STM32非DMA模式下读取多通道AD采样值
折腾了几天了,还没有把DMA弄得明白,现在把自己做的双通道的AD采样记录一下,免得忘得太快了。
上篇文章已经讲得很详细了,对于ADC的采样,有几个结构需要初始化:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);// 使能 ADC1时钟线
/* ADC1 configuration */
ADC_InitStructure.ADC_Mode = ADC_Mode_I //独立工作模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式
//为了保证单次通道采集不被覆盖,只好委屈求全了,注意这里的两个DISABLE!!!!!
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_N //软件控制转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R //右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);//这里是个转折点,如果没有使能,会永远卡在这一点,死机了。。。。
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
下面就可以进入真正的ADC配置了,双通道示意。
void GetADValue(void)
for(i=0;i&2;i++)
/* ADC1 regular channel_8,configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5);//转换时间为17.1US
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5);//转换时间为17.1US
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);//此处与下面的DISABLE呼应,不可省略,虽然前面已经交代过了。
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//我原以为应该是SET,但实际测试结果让我深思良久
//EOC为0表示转换未完成,但重点还是在那个;,只是在告诉我们等待、等待而已!!!!唉。。。
ADCConvertedValue[i]=ADC_GetConversionValue(ADC1);
//数组存储采样值,便于调用查看。
ADC_ClearFlag(ADC1, ADC_FLAG_EOC); //清除EOC,DMA时读数据,硬件自动清除
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
ADC_Cmd(ADC1, DISABLE);//与上文呼应,完成一次采样,保证准确性。前面加个延时更为妥当。
写到这里应该就够明显了,最重要的思想已经表露无遗,剩下的无非就是如何使用采集到的值,还是各显神通吧!!
原文链接:
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
今日搜狐热点09:38 提问
stm32adc配置问题应用到adc+dma+tim+usart
我将adc配置后读出的数一直为0,怀疑是否adc没有运作。下面是我写的程序,请大神们帮我指点一下,看看哪出了问题。
**********************************************************************************/
#include "adc.h"
vu16 AD_Value[N][M];
//用来存放ADC转换结果,也是DMA的目标地址
vu16 After_filter[M];
//用来存放求平均值之后的结果
u16 AD_Data_Ram[N];
u16 Get_RF_Data[N];
extern u16 RF_ADC1_Value_Count[ADRF_Arr_Count];
extern u16 V_ADC1_Value[ADRF_Arr_Count];
//存储采集电池电压缓存
函数名:ADC1_GPIO_Config
:使能ADC1和DMA1的时钟,初始化PC.01
:内部调用/
static void ADC1_GPIO_Config(void)
GPIO_InitTypeDef GPIO_InitS
/ Enable ADC1 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB, ENABLE);
/*PB0-RF_AD输入 PB1-电压检测输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 函数名:ADC1_Mode_Config
:配置ADC1的工作模式为DMA模式
:内部调用/
static void ADC1_Mode_Config(void)
ADC_InitTypeDef ADC_InitS
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/ ADC1 configuration */
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure); //初始化ADC结构体
ADC_InitStructure.ADC_Mode = ADC_Mode_I
//独立ADC模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
//扫描模式用于多通道采集
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//ENABLE 开启连续转换模式,即不停地进行ADC转换
ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_N
//ADC_ExternalTrigConv_T2_CC2;//外部触发设置为TIM2
//(ADC_ExternalTrigConv_N
//不使用外部触发转换 (ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO; )//使用外部中断线11作为转换外部触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
//采集数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = M;
//要转换的通道数目2
ADC_Init(ADC1, &ADC_InitStructure);
/*配置ADC时钟,为PCLK2的8分频,即9MHz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
/*配置ADC1的通道8为55.5个采样周期,序列为1 /
/配置ADC1的通道9为55.5个采样周期,序列为2 /
ADC_SampleTime_55Cycles5
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5);
/ Enable ADC1 external trigger /
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
/ Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/*复位校准寄存器 /
ADC_ResetCalibration(ADC1);
/等待校准寄存器复位完成 */
while(ADC_GetResetCalibrationStatus(ADC1));
/* ADC校准 /
ADC_StartCalibration(ADC1);
/ 等待校准完成*/
while(ADC_GetCalibrationStatus(ADC1));
/* 由于没有采用外部触发,所以使用软件触发ADC转换 */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA
void DMA_AD_Init(void)
DMA_InitTypeDef DMA_InitS
/* Enable DMA clock /
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/ DMA channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_V//内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = N*M;
//DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D//外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//内存地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW //半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW
DMA_InitStructure.DMA_Mode = DMA_Mode_C
//循环传输
DMA_InitStructure.DMA_Priority = DMA_Priority_H //DMA通道拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_D
//DMA通道没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//开启DMA传输完成中断
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
DMA_ClearITPendingBit(DMA_IT_TC);
//清除一次DMA中断标志
DMA_Cmd(DMA1_Channel1, ENABLE); //Enable DMA channel1
函数名:ADC1_Init
:外部调用
void ADC1_Init(void)
ADC1_GPIO_Config();
DMA_AD_Init();
ADC1_Mode_Config();
按赞数排序
我就是按这个配置的,结果还是不行。你帮我查看一下,我这个程序有问题吗,在哪
//USART 初始化设置
USART_InitStructure.USART_BaudRate =//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_N//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
//使用DMA检测串口空闲中断初始化配置
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//开启空闲中断
/*开启串口DMA接收*/
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
USART_Cmd(USART1, ENABLE);
//使能串口
USART1_Flag=0;
//发送一个字节
void TransByte(USART_TypeDef* USARTx , u8 byte)
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)!=SET);//等待 发送结束
USART_SendData(USARTx, byte);//向串口 1 发送数据
LED4=!LED4;
Delay_ms(5);
//这个时间由接收的器件决定,如果过快接收不了
//发送一个字符串
void TransStr(USART_TypeDef* USARTx , u8 *Str)
while(Str[i]!='\0')//空字符
TransByte(USARTx,Str[i]);
//串口1接收函数
void USART1_IRQHandler(void)
//串口1中断服务程序
volatile u16 IIR;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
//是否为接收中断
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除标志位
ch=USART_ReceiveData(USART1);
if(ch!=0x0A) //接收字符不是换行符
USART1_RX_BUF[USART1_RX_Count]=
USART1_RX_Count++;
if(USART1_RX_BUF[USART1_RX_Count-1]==0x0D)
//接收到前一个字符为回车符
USART1_Flag=1;
USART1_RX_Count=0;
LED4=!LED4;
void USART11_IRQHandler(void)
//串口1空闲中断服务程序
unsigned char num=0;
if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)
num = USART1-&SR;
num = USART1-&DR; //清USART_IT_IDLE标志
DMA_Cmd(DMA1_Channel5,DISABLE);
num = USART_REC_LEN -
DMA_GetCurrDataCounter(DMA1_Channel5);
//得到真正接收数据个数
//USART1_RX_BUF[num] = '\0';
DMA1_Channel5-&CNDTR=USART_REC_LEN;
//重新设置接收数据个数
DMA_Cmd(DMA1_Channel5,ENABLE);
USART1_Flag = 1;
//接收数据标志位置1
LED3=!LED3;
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐如何将STC单片机的10位ADC读取的值转换为0到1023_单片机吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:149,287贴子:
如何将STC单片机的10位ADC读取的值转换为0到1023收藏
如何将STC单片机的10位ADC读取的值转换为0到1023之间的数字?现在读出来的值为unsigned int型ADC_DATA=ADC_RES*4+ADC_RESL;
同步整流升压芯片,小封装升压芯片,大电流升压芯片,免费提供样品及DEM板测试,快充3V升12V/1.5A升压方案 免费提供样品板联系:
对于单片机来说,两者相同,这个很重要,本质上就是这么多数,单片机认2进制我们是10进制。如果你是要用来显示的话,你需要,将他们各个位分离开,放入数组,分别显示 likedatas[0] = temp / 10000;
datas[1] = temp % 10000 / 1000;
datas[2] = temp % 1000 / 100;
datas[3] = temp % 100 / 10;
datas[4] = temp % 10;这个只是示意,你要把adc_data放入temp一步一步除再把结果在另外的程序显示就好了在另外那个也回了,看到了给分偶,
二进制转十进制
不存在进制转换的问题,本来就是这么多数,是什么进制只是写法不同
不存在进制转换 读出来多少就是多少二进制和十进制只是表示不一样 大小是一样的二进制只是存储在单片机中的形式
登录百度帐号【原创经典】Kinetis 16-bit ADC+DMA+定时器实现AutoScan自动通道扫描采样
这次是我第一次尝试在“原创”的后面又加了经典俩字,至于为啥(俺的东北话又情不自禁冒出来了,呵呵),一个是自己一时兴起(今天心情相比于前段时间稍好些),二个是我自认为本篇文章是俺的一篇得意之作而且对广大Kinetis用户也是非常有用的一篇技术博文(对俺来说担当的起“经典”俩字),所以为了避免自己有沽名钓誉之嫌有必要在这里解释一下,呵呵。当然了,不能说俺之前的文章不经典啦(那岂不是在打自己的脸,哈哈),只是相对来说,我觉着这篇文章对一些应用场合更有实际的意义。咳咳,好吧,自己不小心又唠叨了这么多,发现自打写博客之后我都快成为话唠了,用那句经典的广告语来说就是“根本停不下来”啊,呵呵~
好了,言归正传,我之前不止在一篇博客里面提到过飞思卡尔Kinetis独有的片内16位高精度ADC(其他家大多都是12位的),这个16位分辨率的ADC,虽然其不可能精度达到全16位,但是其最高13/14位的精度也不是其他12位ADC能比的(而且其还支持单端和差分输入,自带PGA和硬件平均功能),所以Kinetis在一些比如温度、重量和电池电压监控等测量方面的应用有其独特的优势。但是让人又爱又恨的是,这个16位ADC不支持通道自动扫描的功能,也就是说每次转换一个通道都需要软件或硬件触发一次(估计上这是一种成本上的妥协和折衷吧),这个问题对上面所提到的温度和重量等大滞环系统没有影响(他们本身对你时间没有太高的要求,一个个慢慢转换就是了),但是在一些对信号的采样率和实时性要求比较高的场合,如果使用查询等待的方式会干耗掉CPU的资源,而使用中断方式的话又会有太多的中断响应。那有没有一种比较优化的方式实现来满足这种对采样率和实时性要求较高的需求呢,咳咳,有点废话了,没有的话我写这篇文章干嘛,呵呵,所以本篇的主要目的就是通过使用ADC+DMA+定时器来灵活实现Kinetis内部ADC自动通道扫描的方法,下面开整,走着:测试平台:YL_KL26(优龙做的基于KL26的开发板,与FSL官方的FRDM-KL26很相近) 开发环境:IARv7.3 测试代码:基于FRDM-KL26Z_SC\FRDM-KL26Z_SC_Rev_1.0\klxx-sc-baremetal\build\iar\hello_world代码修改 功能描述:以100ksps的采样率对ADC的Channel0(接到YL-KL26板载的变阻器)和Channel26(KL26内部温度传感器)以DMA方式扫描采样,对一个Buffer存满10次采样数据后切换到另一个Buffer继续存,而对之前的Buffer进行处理(数组的偶数元素存的是Channel0的数据,奇数元素存的是Channel26的数据),从而实现双缓存。 (1)首先定义需要用到的变量和宏,如下所示,其中BUFFER_SIZE定义了Buffer的存储深度(为了测试,我先只定义了10个数组,其中5个for Channel0的数据,5个for Channel26的数据),pCounter用来做双缓存的切换计数,ADC_Channel数组为要采样的Channel list(至于本来是2个通道,为什么定义成4个数组,这是由于DMA的Circular Buffer模数计数最小为16个字节构成循环,一个Channel占用4个字节,所以最少定义4个元素,凑足16个字节),而剩下的Result_Buffer和Buffer_Address则为数据缓存和缓存的首地址,用来做DMA目的地址;#define BUFFER_SIZE
#pragma data_alignment = 16 //The ADC_Channel address should be align with the DMA Circular buffer size
uint32 ADC_Channel[4]={0, 26, 0, 26};
//Channel list for Channel0 and Channel 26
unsigned char pCounter=0;
// Counter used for Dual buffer switch
uint8 Result_Buffer1[BUFFER_SIZE]={0};
uint8 Result_Buffer2[BUFFER_SIZE]={0};
uint32 Buffer_Address[2]={(uint32)&Result_Buffer1, (uint32)&Result_Buffer2};
//Buffer list(2)其次初始化ADC模块(为了方便我定义成8位分辨率),禁止ADC转换完成中断,使能ADC转换完成触发DMA,同时使能单次软件触发模式(即每次写入ADC0_SC1的通道号触发一次ADC转换)。需要注意的是ADC的输入时钟源要小于18MHz;void init_ADC8(void)
// Turn on the ADC0 clock
SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK );
ADC0_CFG1 = ADC_CFG1_ADIV(1)
//divide ratio is 2 and the clock rate is (input clock)/2.
| ADC_CFG1_MODE(0)
// single-end 8bit mode
| ADC_CFG1_ADICLK(0);
//Bus clock
ADC0_CFG2 = 0;
ADC0_CV1 =
// can be anything
ADC0_CV2 = 0x5678u;
// can be anything
ADC0_SC2 = 0 | ADC_SC2_DMAEN_MASK;
//ADC conversion complete DMA enable
ADC0_SC3 = 0;
// Hardware average disable and once conversion
(3)然后初始化TPM定时器模块,该模块配置成自由计数模式,溢出中断触发DMA,其中MOD寄存器即溢出时间决定ADC的采样率,本例程配置成每100kHz的频率溢出一次;void init_TPM1(void)
SIM_SCGC6 |= (SIM_SCGC6_TPM1_MASK );
SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1); //input clock source is MCGPLL/2=24MHz
TPM1_SC = TPM_SC_DMA_MASK | TPM_SC_PS(3);//Divide by 3M=24M/8
TPM1_CNT = 0;
TPM1_MOD = 30;
//timer interrupt triger with 100ksps
TPM1_SC |= TPM_SC_CMOD(1);
//start the counter
(4)这部分是DMA的初始化,本例程的核心部分,本例程的实现需要使用两个Channel的DMA,其中一个channel的DMA与TPM定时器配合实现周期性触发ADC转换,即每次TPM定时器溢出触发一次DMA将Channellist的通道号写到ADC_SC1寄存器从而触发一次ADC转换,然后ADC转换完成触发另一个DMA Channel将ADC的结果传到其中一个Buffer,具体配置俺就不多说了,看下面的程序注释就行了,至于TPM和ADC在DMA中的触发源可以在KL16的参考手册中找到,如下图,其中ADC0的触发源为40,TPM1溢出触发源为55;void DMA_2ChanelADC_Init(void)
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;
enable_irq(INT_DMA1-16);
DMA_SAR0 = (uint32) &ADC_C
//Set source address to ADC_Channel
DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(4*BUFFER_SIZE);
//Set BCR to know how many bytes to transfer, 8 bytes for two 32-bit transfer
DMA_DCR0 &= ~(DMA_DCR_SSIZE_MASK | DMA_DCR_DSIZE_MASK);
//Clear source size and destination size fields
/* Set DMA as follows:
Source size is 32-bit size
Destination size is 32-bit size
Cycle steal mode
External requests are enabled
source address increments 1 automatically
DMA_DCR0 |= (DMA_DCR_SSIZE(0)
| DMA_DCR_DSIZE(0)
| DMA_DCR_CS_MASK
| DMA_DCR_ERQ_MASK
| DMA_DCR_SINC_MASK
| DMA_DCR_SMOD(1)); //16 bytes circular buffer
DMA_DAR0 = (uint32) &ADC0_SC1A;//0x;
//Set source address to ADC0_SC1A
DMAMUX0_CHCFG0 = DMAMUX_CHCFG_SOURCE(55);
//Select TPM1 overflow as channel source
DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK;
//Enable the DMA MUX channel
/*********************************************************************/
DMA_SAR1 = (uint32) &ADC0_RA;//0x;
//Set source address to ADC0_RA
DMA_DSR_BCR1 = DMA_DSR_BCR_BCR(BUFFER_SIZE);
//Set BCR to know how many bytes to transfer
DMA_DCR1 &= ~(DMA_DCR_SSIZE_MASK | DMA_DCR_DSIZE_MASK);
//Clear source size and destination size fields
/* Set DMA as follows:
Source size is 8-bit size
Destination size is 8-bit size
Cycle steal mode
External requests are enabled
Destination address increments 1 automatically
BCR Bytes trasfer completed interrupt enable
if ((DMA_DSR_BCR1 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
DMA_DSR_BCR1 |= DMA_DSR_BCR_DONE_MASK;
DMA_DCR1 |= (DMA_DCR_SSIZE(1)
| DMA_DCR_DSIZE(1)
| DMA_DCR_CS_MASK
| DMA_DCR_ERQ_MASK
| DMA_DCR_DINC_MASK
| DMA_DCR_EINT_MASK);
DMA_DAR1 = (uint32) &Result_Buffer1;
//Set source address to result buffer
DMAMUX0_CHCFG1 = DMAMUX_CHCFG_SOURCE(40);
//Select ADC0 COCO flag as channel source
DMAMUX0_CHCFG1 |= DMAMUX_CHCFG_ENBL_MASK;
//Enable the DMA MUX channel
(5)最后是DMA中断服务函数的配置,这也是一个核心部分,主要涉及到双缓存的切换(可以看到DMA Channel1的目的地址在两个buffer地址之间切换),另外一定记得每进一次DMA完成中断都要重新填一次DMA_DSR_BCR寄存器让其重新开始计数,还有可能有博友比较疑惑的是为啥BCR0的size是BCR1的一倍,这是因为DMA Channel0每次传输的是32位即4个字节的ADC采样通道号(写32位的ADC_SC1寄存器),而DMA Channel1每次传输8位即一个字节的ADC结果(因为我前面把其配置成8位单端模式了),所以这个比例是4:1,如果配置成16位ADC模式的话,这个比例就该改成2:1了,而且前面DMA初始化部分也需要做相应修改。void DMA1_IRQHandler(void)
/* Create pointer & variable for reading DMA_DSR register */
if ((DMA_DSR_BCR1 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;
//Clear Done bit
DMA_DSR_BCR1 |= DMA_DSR_BCR_DONE_MASK;
//Clear Done bit
if(++pCounter>=2)
pCounter=0;
DMA_DAR1 = (uint32) Buffer_Address[pCounter];
//Set source address to result buffer
DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(4*BUFFER_SIZE);
//Reset BCR
DMA_DSR_BCR1 = DMA_DSR_BCR_BCR(BUFFER_SIZE);
//Reset BCR
(6)好了,一切准备完毕(当然还有一些具体的细节操作,包括把DMA1中断函数加载到中断向量表等,我就不多做介绍了,可以参考我博文下面附件中的样例工程),编译链接整个工程,然后下载到板子并运行。结果如下图所示,可以看到每进一次中断(即BCR值减到0)切换一次Buffer地址,实现双缓存,效果还是不错的,呵呵。此外,该工程也比较灵活,通过修改BUFFER_SIZE宏来修改采样数据的存储深度,修改TPM1_MOD值来配置ADC的采样率,当然需要注意这个采样率不要超过ADC在当前输入时钟频率下不要超过其最大的转换率,至于原因,你懂的。。。
呼呼,一下子写了不少,估计需要博友们好好消化一下了。经此一役,发现通过DMA还是可以有很多想象的空间的,只有想不到没有做不到,哈哈。好了,写的有点多,休息一下,准备再战,呵呵,未完待续~附件为完整IAR下的测试工程:
关注微信公众号查看: 5966|回复: 20
【STC89c51+adc0832】关于读取0832的AD转换值
本帖最后由 疯糖蔚男的天 于
09:51 编辑
读取值转换后始终未5.00,读数不变,不知道是不是串行数据读取出了问题。。uchar AD_READ()
{
& & & & uchar i,DAT1=0,DAT2=0;
& & & & ADC_CS=0;& & & & & & & & & & & && & //片选信号(低有效)
& & & & ADC_CLK=0;& & & & & & & &&&//第一个时钟脉冲
& & & & ADC_DI=1;& & & & & & & &&&//& & & &&&DI输入起始信号(高电平有效)
& & & & _nop_();& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & ADC_CLK=1;& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & ADC_CLK=0;& & & & & & & &&&//*****************************
& & & & ADC_DI=1;& & & & & & & &&&//输入第一位通道选择数据& & & & 1
& & & & _nop_();& & & & & & & &&&//& & & & & & & & & & & & & & & & & & & && && & MUX Address& & & && && && &&&Channel
& & & & _nop_();& & & & & & & &&&//& & & & & & & & & & & & & & & & & & & && &SGL/DIF& & & & ODD/SIGN& && && &&&0& && && &1
& & & & ADC_CLK=1;& & & & & & & &&&//& && && && && && && && && && && & & & & & & &&&1& & & & & & & && &&&0& &&&+
& & & & _nop_();& & & & & & & &&&//& & & & & & & & & & & & & & & & & & & &&&1& && && && && && && && && && && &1& & & && && & +
& & & & _nop_();& & & & & & & &&&//& & & & & & & & & & & & & & & & & & & &&&0& & & & & & & && &&&0& && &+& && &&&-
& & & & ADC_CLK=0;& & & & & & & &&&//**********************& & & && && && && && && &0& & & & & & & && &&&1& && & -& && &&&+
& & & & ADC_DI=0;& & & & & & & &&&//输入第二位通道选择数据& & & & 0
& & & & _nop_();& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & ADC_CLK=1;& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & ADC_CLK=0;& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//
& & & & _nop_();& & & & & & & &&&//**********************
& & & & ADC_DI=1;
& & & & ADC_CLK=1;
& & & & for(i=0;i&8;i++)& & & & & & & & //读取8位数据
& & & & & & & & DAT1|=ADC_DO;& & & & & & & &
& & & & & & & & ADC_CLK = 1;
& & & & & & & & _nop_();
& & & & & & & & _nop_();
& & & & & & & & ADC_CLK = 0;
& & & & & & & & _nop_();
& & & & & & & & _nop_();
& & & & & & & & DAT1&&=1;
& & & & & & & & DAT1|=(unsigned char)ADC_DO;
& & & & & & & & if(DAT1==7)
& & & & & & & & DAT1|=ADC_DO;
& & & & & & & & if(ADC_DO)
& & & & & & & & DAT1|=0x80&&i;
& & & & for(i=0;i&8;i++)& & & & & & & & //读取8位相反数据
& & & & & & & & if(ADC_DO)DAT2|=0x01&&i;
& & & & & & & & ADC_CLK = 1;
& & & & & & & & ADC_CLK = 0;
& & & & & & & & _nop_();
& & & & }& & & &
& & & & ADC_CS = 1;ADC_DI = 1; ADC_CLK = 1;& & & & //读取完成释放总线
& & & & if(DAT1==DAT2)& & & & & & & & & & & & //数据效验如果正确则返回读取数据
& & & & return DAT1;
}
复制代码。
补充内容 ( 14:10):
找到原因了,DO引脚压根没有有效与单片机连接,接插件锈了…………;P
童鞋们,写驱动的同时要保证硬件给力啊!!!
显示值是这样的,AD读取顺序都是按照PDF上面来的,就串行数据读不来
1.jpg (39.6 KB, 下载次数: 5)
09:47 上传
百度文库里有AD0832的程序,拿来就可以用了
黑米竹子 发表于
百度文库里有AD0832的程序,拿来就可以用了
那个永远是别人的&&看不懂的&&抄也没用
看来我还是慢慢改吧&&
<p id="rate_99" onmouseover="showTip(this)" tip="精彩回帖~~~~~~~~&经验 + 3 点
" class="mtn mbn">
标准程序,我一拿就好用
黑米竹子 发表于
标准程序,我一拿就好用
看得头大,,每个程序都有不同的方法,但是本质是一样的,为什么我的就不行呢
给你一个参考一下,建议你程序要一点点的加上去。
11:11 上传
点击文件名下载附件
29.13 KB, 下载次数: 448
w6955 发表于
给你一个参考一下,建议你程序要一点点的加上去。
谢谢朋友的资料!我再慢慢找下错误,等调试成功再来汇报!
调试发现AD返回值一直是0xff,所以一直显示为5.00v,这说明AD转换没有做好
但是,,,但是,,,程序和很多网络上的都一样啊,包括w6955朋友上传的资料,可为什么总是不对呢
百思不得其解…………百思不得其解…………百思不得其解…………百思不得其解…………
最后找到问题的关键了
2.jpg (46.51 KB, 下载次数: 6)
14:03 上传
w6955 发表于
给你一个参考一下,建议你程序要一点点的加上去。
原因找到了&&是因为DO引脚没有有效连接,,,接插件锈迹斑斑,坑爹了……
我发一个贴,然后自己终结……
还是得发个贴鼓励自己找原因啊!想想这个弄了两三天了,一直没结果,找到原因我哭笑不得!
东西够久的,,看去垃圾站捡来的
黑米竹子 发表于
东西够久的,,看去垃圾站捡来的
哈哈~&&差不多算是‘捡’来的。不过在这上面用用数码管,跑跑流水灯神马的还是可以的,小撸怡情
疯糖蔚男的天 发表于
原因找到了&&是因为DO引脚没有有效连接,,,接插件锈迹斑斑,坑爹了……&&
写完了一点就调试、一个一个子程序的调试,这个方法很重要
w6955 发表于
写完了一点就调试、一个一个子程序的调试,这个方法很重要
当然!我先写好的显示,然后做AD的转换和显示,显示倒是很早就出来了,但就是数值不对,刚刚一一改变数值查看,发现就出在读取AD值那块,最后怀疑芯片,一一查看引脚,发现其与单片机连接不良…
Powered by}

我要回帖

更多关于 asp radio只读取到值 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信