本帖最后由 qjp1988113 于 2020-11-2 10:38 编辑
今天有空,试一下PIC-IoT WA开发板上PIC24FJ128的ADC功能,我们测试板上的光敏传感器在不同亮度下的分压。
电路如下:
PIC24FJ128的ADC支持10BIt/12BIT的采样模式。我们这里用12BIT,软件触发非扫描的形式采样,毕竟就用了一个通道么。
采样速度最高200K/S,普通也够用了。
下面进行代码的配置:
生成的ADC的程序:
C文件:
/**
Section: Included Files
*/
#include "adc1.h"
/**
Section: File Specific Functions
*/
// ADC1 Default Interrupt Handler
static void (*ADC1_DefaultInterruptHandler)(void) = NULL;
/**
Section: Driver Interface
*/
void ADC1_Initialize (void)
{
// ASAM enabled; DMABM disabled; ADSIDL disabled; DONE disabled; DMAEN disabled; FORM Absolute decimal result, unsigned, right-justified; SAMP disabled; SSRC Internal counter ends sampling and starts conversion; MODE12 12-bit; ADON enabled;
AD1CON1 = 0x8474;
// CSCNA disabled; NVCFG0 AVSS; PVCFG AVDD; ALTS disabled; BUFM disabled; SMPI Generates interrupt after completion of every sample/conversion operation; BUFREGEN disabled;
AD1CON2 = 0x00;
// SAMC 31; EXTSAM disabled; PUMPEN disabled; ADRC RC clock; ADCS 0;
AD1CON3 = 0x9F00;
// CH0SA AN0; CH0SB AN0; CH0NB AVSS; CH0NA AVSS;
AD1CHS = 0x00;
// CSS30 disabled; CSS29 disabled; CSS28 disabled;
AD1CSSH = 0x00;
// CSS9 disabled; CSS8 disabled; CSS7 disabled; CSS6 disabled; CSS5 disabled; CSS4 disabled; CSS3 disabled; CSS2 disabled; CSS15 disabled; CSS1 disabled; CSS14 disabled; CSS0 disabled; CSS13 disabled; CSS12 disabled; CSS11 disabled; CSS10 disabled;
AD1CSSL = 0x00;
// DMABL Allocates 1 word of buffer to each analog input;
AD1CON4 = 0x00;
// ASEN disabled; WM Legacy operation; ASINT No interrupt; CM Less Than mode; BGREQ disabled; CTMREQ disabled; LPEN disabled;
AD1CON5 = 0x00;
// CHH9 disabled; CHH8 disabled; CHH7 disabled; CHH6 disabled; CHH5 disabled; CHH4 disabled; CHH3 disabled; CHH2 disabled; CHH1 disabled; CHH0 disabled; CHH11 disabled; CHH10 disabled; CHH13 disabled; CHH12 disabled;
AD1CHITL = 0x00;
// CTMEN30 disabled; CTMEN29 disabled; CTMEN28 disabled;
AD1CTMENH = 0x00;
// CTMEN5 disabled; CTMEN6 disabled; CTMEN7 disabled; CTMEN8 disabled; CTMEN9 disabled; CTMEN12 disabled; CTMEN13 disabled; CTMEN10 disabled; CTMEN0 disabled; CTMEN11 disabled; CTMEN1 disabled; CTMEN2 disabled; CTMEN3 disabled; CTMEN4 disabled; CTMEN14 disabled; CTMEN15 disabled;
AD1CTMENL = 0x00;
// AD1RESDMA 0;
AD1RESDMA = 0x00;
// VBGEN3 disabled; VBGEN2 disabled; VBGEN1 disabled;
ANCFG = 0x00;
//Assign Default Callbacks
ADC1_SetInterruptHandler(&ADC1_CallBack);
}
void __attribute__ ((weak)) ADC1_CallBack(void)
{
}
void ADC1_SetInterruptHandler(void* handler)
{
ADC1_DefaultInterruptHandler = handler;
}
void __attribute__ ((weak)) ADC1_Tasks ( void )
{
if(IFS0bits.AD1IF)
{
if(ADC1_DefaultInterruptHandler)
{
ADC1_DefaultInterruptHandler();
}
// clear the ADC interrupt flag
IFS0bits.AD1IF = false;
}
}
/*******************************************************************************
!!! Deprecated Definitions and APIs !!!
!!! These functions will not be supported in future releases !!!
*******************************************************************************/
void ADC1_Start(void)
{
AD1CON1bits.SAMP = 1;
}
void ADC1_Stop(void)
{
AD1CON1bits.SAMP = 0;
}
uint16_t ADC1_ConversionResultBufferGet(uint16_t *buffer)
{
int count;
uint16_t *ADC16Ptr;
uint16_t sampleCount = AD1CON2bits.SMPI;
ADC16Ptr = (uint16_t *)&(ADC1BUF0);
for(count=0;count<=sampleCount;count++)
{
buffer[count] = (uint16_t)*ADC16Ptr;
ADC16Ptr++;
}
return count;
}
/**
End of File
*/
h文件:
#ifndef _ADC1_H
#define _ADC1_H
/**
Section: Included Files
*/
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus // Provide C++ Compatibility
extern "C" {
#endif
/**
Section: Data Types
*/
/** Scan Selected Macro Definition
[url=home.php?mod=space&uid=267864]@summary[/url]
Defines the scan option selection done for the shared channels.
@Description
This macro defines the scan option selection done for the shared channels.
Remarks:
None
*/
#define ADC1_SCAN_MODE_SELECTED false
/** ADC1 Channel Definition
[url=home.php?mod=space&uid=267864]@summary[/url]
Defines the channels selected.
@Description
This routine defines the channels that are available for the module to use.
Remarks:
None
*/
typedef enum
{
Light_In,//Channel Name:AN8 Assigned to:Shared Channel
CHANNEL_CTMU_temperature_sensor_input,//Channel Name:CTMU temperature sensor input Assigned to:Shared Channel
CHANNEL_CTMU,//Channel Name:CTMU Assigned to:Shared Channel
CHANNEL_VBG,//Channel Name:VBG Assigned to:Shared Channel
CHANNEL_AVSS,//Channel Name:AVSS Assigned to:Shared Channel
CHANNEL_AVDD,//Channel Name:AVDD Assigned to:Shared Channel
} ADC1_CHANNEL;
/**
Section: Interface Routines
*/
/**
@Summary
Initializes ADC1 module.
@Description
This routine initializes ADC1 module, using the given initialization data.
This routine must be called before any other ADC routine is called.
@Preconditions
None.
@Param
None.
@Returns
None
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
void ADC1_Initialize (void);
/**
@Summary
Enables the ADC1 module.
@Description
This routine is used to enable the ADC1 module.
@Preconditions
ADC1_Initialize function should have been called
before calling this function.
@Param
None.
@Returns
None.
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static void ADC1_Enable(void)
{
AD1CON1bits.ADON = 1;
}
/**
@Summary
Disables the ADC1 module.
@Description
This routine is used to disable the ADC1 module.
@Preconditions
ADC1_Initialize function should have been called
before calling this function.
@Param
None.
@Returns
None.
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static void ADC1_Disable(void)
{
AD1CON1bits.ADON = 0;
}
/**
@Summary
Starts sampling manually.
@Description
This routine is used to start sampling manually.
@Preconditions
ADC1_Initialize function should have been called
before calling this function.
@Param
None.
@Returns
None.
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static void ADC1_SoftwareTriggerEnable(void)
{
AD1CON1bits.SAMP = 1;
}
/**
@Summary
Stops sampling manually.
@Description
This routine is used to stop the sampling manually.
@Preconditions
ADC1_Initialize() function should have been
called before calling this function.
@Param
None.
@Returns
None.
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static void ADC1_SoftwareTriggerDisable(void)
{
AD1CON1bits.SAMP = 0;
}
/**
@Summary
Allows selection of a channel for conversion.
@Description
This routine is used to select desired channel for conversion.
@Preconditions
ADC1_Initialize() function should have been
called before calling this function.
@Param
channel - Channel for conversion
@Returns
None
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static void ADC1_ChannelSelect( ADC1_CHANNEL channel )
{
switch(channel)
{
case Light_In:
AD1CHSbits.CH0SA= 0x8;
break;
case CHANNEL_CTMU_temperature_sensor_input:
AD1CHSbits.CH0SA= 0xE;
break;
case CHANNEL_CTMU:
AD1CHSbits.CH0SA= 0xF;
break;
case CHANNEL_VBG:
AD1CHSbits.CH0SA= 0x1C;
break;
case CHANNEL_AVSS:
AD1CHSbits.CH0SA= 0x1D;
break;
case CHANNEL_AVDD:
AD1CHSbits.CH0SA= 0x1E;
break;
default:
break;
}
}
/**
@Summary
Returns the conversion value for the channel selected.
@Description
This routine is used to get the analog to digital converted value for a
specific channel.
@Preconditions
This routine returns the conversion value only after the conversion is complete.
Conversion completion status can be checked using ADC1_IsConversionComplete(channel)
routine.
@Param
channel - Selected channel
@Returns
Returns the analog to digital converted value
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static uint16_t ADC1_ConversionResultGet( ADC1_CHANNEL channel )
{
uint16_t result;
result = ADC1BUF0;
return result;
}
/**
@Summary
Returns the status of conversion.
@Description
This routine is used to determine if conversion is completed. When conversion
is complete the routine returns true otherwise false.
@Preconditions
ADC1_Initialize() function should have been
called before calling this function.
@Param
channel - Selected channel
@Returns
true - Conversion is complete.
false - Conversion is not complete.
@Example
<code>
int conversion,i=0;
ADC1_Initialize();
ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(channel));
conversion = ADC1_ConversionResultGet(channel);
ADC1_Disable();
</code>
*/
inline static bool ADC1_IsConversionComplete(ADC1_CHANNEL channel)
{
bool status;
status = AD1CON1bits.DONE;
return status;
}
/**
@Summary
Enables interrupts.
@Description
This routine is used to enable the ADC1 interrupt.
@Preconditions
None.
@Param
None.
@Returns
None.
@Example
<code>
ADC1_InterruptEnable();
</code>
*/
inline static void ADC1_InterruptEnable(void)
{
IEC0bits.AD1IE = 1;
}
/**
@Summary
Disables interrupts.
@Description
This routine is used to disable the ADC1 interrupt.
@Preconditions
None.
@Param
None.
@Returns
None.
@Example
<code>
ADC1_InterruptDisable();
</code>
*/
inline static void ADC1_InterruptDisable(void)
{
IEC0bits.AD1IE = 0;
}
/**
@Summary
Clears interrupt flag
@Description
This routine is used to clear the interrupt flag manually.
@Preconditions
None.
@Param
None.
@Returns
None.
@Example
<code>
ADC1_InterruptFlagClear();
</code>
*/
inline static void ADC1_InterruptFlagClear(void)
{
IFS0bits.AD1IF = 0;
}
/**
@Summary
Allows selection of priority for interrupt.
@Description
This routine is used to select desired priority for interrupt.
@Preconditions
None.
@Param
None.
@Returns
None.
@Example
<code>
uint16_t priorityValue;
priorityValue = 0x002;
ADC1_InterruptPrioritySet(priorityValue);
</code>
*/
inline static void ADC1_InterruptPrioritySet( uint16_t priorityValue )
{
IPC3bits.AD1IP = 0x7 & priorityValue;
}
/**
@Summary
Callback for ADC1.
@Description
This routine is callback for ADC1
@Preconditions
None.
@Param
None.
@Returns
None
[url=home.php?mod=space&uid=389923]@example[/url]
<code>
ADC1_CallBack();
</code>
*/
void ADC1_CallBack(void);
/**
@Summary
Assigns a function pointer with a callback address.
@Description
This routine assigns a function pointer with a callback address.
@Preconditions
None.
@Param
Address of the callback routine.
@Returns
None
[url=home.php?mod=space&uid=389923]@example[/url]
<code>
ADC1_SetInterruptHandler(&ADC1_CallBack);
</code>
*/
void ADC1_SetInterruptHandler(void* handler);
/**
[url=home.php?mod=space&uid=267864]@summary[/url]
Polled implementation
@Description
This routine is used to implement the tasks for polled implementations.
@Preconditions
ADC1_Initialize() function should have been
called before calling this function.
@Param
None
@Returns
None
@Example
<code>
ADC1_Tasks();
</code>
*/
void ADC1_Tasks(void);
/*******************************************************************************
!!! Deprecated Definitions and APIs !!!
!!! These functions will not be supported in future releases !!!
*******************************************************************************/
/**
@Summary
Starts sampling manually.
@Description
This routine is used to start the sampling manually.
@Preconditions
ADC1_Initialize function should have been called
before calling this function.
@Param
None.
@Returns
None.
@Example
None.
*/
void __attribute__((deprecated("\nThis will be removed in future MCC releases. \nUse ADC1_SoftwareTriggerEnable instead."))) ADC1_Start(void);
/**
@Summary
Stops sampling manually.
@Description
This routine is used to stop the sampling manually before conversion
is triggered.
@Preconditions
ADC1_Initialize() function should have been
called before calling this function.
@Param
None.
@Returns
None.
@Example
None.
*/
void __attribute__((deprecated("\nThis will be removed in future MCC releases. \nUse ADC1_SoftwareTriggerDisable instead."))) ADC1_Stop(void);
/**
@Summary
Gets the buffer loaded with conversion results.
@Description
This routine is used to get the analog to digital converted values in a
buffer. This routine gets converted values from multiple channels.
@Preconditions
This routine returns the buffer containing the conversion values only after
the conversion is complete. Completion status conversion can be checked using
ADC1_IsConversionComplete() routine.
@Param
None.
@Returns
Returns the count of the buffer containing the conversion values.
@Example
None.
*/
uint16_t __attribute__((deprecated("\nThis will be removed in future MCC releases. \nUse ADC1_ConversionResultGet instead."))) ADC1_ConversionResultBufferGet(uint16_t *buffer);
#ifdef __cplusplus // Provide C++ Compatibility
}
#endif
#endif //_ADC1_H
/**
End of File
*/
h文件里老是插入一些函数的写法,又不要define,起码看起来归类好些。但是用肯定是正常的。
新建light_in.c和light_in.h
light_in.c:
#include "light_in.h"
//NEW ADD
uint16_t ADC1_GetConversion(ADC1_CHANNEL channel)
{
int conversion,i=0;
ADC1_Initialize();
//ADC1_Enable();
ADC1_ChannelSelect(channel);
ADC1_SoftwareTriggerEnable();
//Provide Delay
for(i=0;i <1000;i++)
{
}
ADC1_SoftwareTriggerDisable();
while (!ADC1_IsConversionComplete(channel))
{
}
conversion = ADC1_ConversionResultGet(channel);
//ADC1_Disable();
return conversion;
}
uint16_t SENSORS_getLightValue(void)
{
return ADC1_GetConversion(LIGHT_SENSOR_ADC_CHANNEL);
}
light_in.h:
/*
* File: light_in.h
* Author: Administrator
*
* Created on November 2, 2020, 8:50 AM
*/
#ifndef LIGHT_IN_H
#define LIGHT_IN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "../mcc_generated_files/adc1.h"
#define LIGHT_SENSOR_ADC_CHANNEL Light_In
uint16_t ADC1_GetConversion(ADC1_CHANNEL channel);
uint16_t SENSORS_getLightValue(void);
#ifdef __cplusplus
}
#endif
#endif /* LIGHT_IN_H */
在mian函数while循环里调用:
int nowLight=0;
nowLight= SENSORS_getLightValue();
printf("the light is : %d\r\n",nowLight);
编译下载,查看串口输出:
有±20个最小单位的跳到,效果还是不错的。
本次实验比较简单,但ADC配置那块还得注意些,ADC就到这。
|