📄 lh7a404_adc_driver.c
字号:
* arg : Not used
*
* Outputs: None
*
* Returns: The pointer to a ADC config structure or 0
*
* Notes: None
*
**********************************************************************/
INT_32 adc_open(void *ipbase,
INT_32 arg)
{
INT_32 status = 0;
if ((adccfg.init == FALSE) && ((ADC_REGS_T *) ipbase == ADC))
{
/* Device is valid and not previously initialized */
adccfg.init = TRUE;
/* Save and return address of peripheral block */
adccfg.regptr = (ADC_REGS_T *) ipbase;
/* Place ADC in a default state */
adc_default(adccfg.regptr);
/* Empty ring buffer and set conversion counter to 0 */
adccfg.rx_head = adccfg.rx_tail = 0;
adccfg.conv_count = 0;
/* Clear default callback vector addresses for pendown and
brownout interrupts */
adccfg.bro_cbfunc = (PFV) NULL;
adccfg.pd_cbfunc = (PFV) NULL;
/* Return pointer to ADC configuration structure */
status = (INT_32) &adccfg;
}
return status;
}
/***********************************************************************
*
* Function: adc_close
*
* Purpose: Close the ADC
*
* Processing:
* If init is not TRUE, then return _ERROR to the caller as the
* device was not previously opened. Otherwise, disable the ADC
* interface and controller by calling adc_default(), and return
* _NO_ERROR to the caller.
*
* Parameters:
* devid: Pointer to ADC config structure
*
* Outputs: None
*
* Returns: The status of the close operation
*
* Notes: None
*
**********************************************************************/
STATUS adc_close(INT_32 devid)
{
ADC_CFG_T *adccfgptr = (ADC_CFG_T *) devid;
STATUS status = _ERROR;
if (adccfgptr->init == TRUE)
{
/* Restore ADC to a default state */
adc_default(adccfg.regptr);
status = _NO_ERROR;
adccfgptr->init = FALSE;
}
return status;
}
/***********************************************************************
*
* Function: adc_ioctl
*
* Purpose: ADC configuration block
*
* Processing:
* This function is a large case block. Based on the passed function
* and option values, set or get the appropriate ADC parameter.
*
* Parameters:
* devid: Pointer to ADC config structure
* cmd: ioctl command
* arg: ioctl argument
*
* Outputs: None
*
* Returns: The status of the ioctl operation
*
* Notes: None
*
**********************************************************************/
STATUS adc_ioctl(INT_32 devid,
INT_32 cmd,
INT_32 arg)
{
ADC_REGS_T *adcregsptr;
UNS_32 tmp, tmp1, tmp2;
ADC_CH_CONV_T *chcfgptr;
ADC_CFG_T *adccfgptr = (ADC_CFG_T *) devid;
STATUS status = _ERROR;
if (adccfgptr->init == TRUE)
{
status = _NO_ERROR;
adcregsptr = adccfgptr->regptr;
switch (cmd)
{
case ADC_SET_CLOCK:
/* Set base speed of ADC clock in Hz */
/* Try to find best ADC clock at or below desired
clock */
tmp1 = 0;
tmp2 = 1;
while ((tmp1 < 7) &&
((CLOCK_MAINOSC / tmp2) > (UNS_32) arg))
{
tmp1++;
tmp2 = tmp2 * 2;
}
/* Best divider found, use it */
tmp = adcregsptr->adcpcr & ~ADC_CLKSEL_MASK;
adcregsptr->adcpcr = (tmp | ADC_CLKSEL_SET(tmp1));
break;
case ADC_CLEAR_FIFO:
/* Clear the ADC sample FIFO */
while ((adcregsptr->adcfifosts & ADC_FIFO_EMPTY) == 0)
{
tmp = adcregsptr->adcresults;
}
break;
case ADC_ENABLE_IREF:
/* Enable or disable the internal reference buffer */
if (arg == 1)
{
adcregsptr->adcpcr |= ADC_REF_ENABLE;
}
else
{
adcregsptr->adcpcr &= ~ADC_REF_ENABLE;
}
break;
case ADC_CLEAR_INTS:
/* Clear pending ADC interrupts */
adcregsptr->adcic = ((UNS_32) arg &
(ADC_EOS_CLR | ADC_PEN_CLR | ADC_BROWNOUT_CLR));
break;
case ADC_INT_ENABLE:
/* Enable ADC interrupts */
adcregsptr->adcie |= ((UNS_32) arg &
(ADC_FIFO_OV_INT | ADC_WATERM_INT |
ADC_EOS_INT | ADC_PEN_INT)) | ADC_GLOBAL_INT;
break;
case ADC_INT_DISABLE:
/* Disable ADC interrupts */
adcregsptr->adcie &= ~((UNS_32) arg &
(ADC_FIFO_OV_INT | ADC_WATERM_INT |
ADC_EOS_INT | ADC_PEN_INT | ADC_GLOBAL_INT));
if (adcregsptr->adcie == ADC_GLOBAL_INT)
{
adcregsptr->adcie = 0;
}
break;
case ADC_INSTALL_BRO:
/* Install the brownout interrupt callback function */
adccfgptr->bro_cbfunc = (PFV) arg;
break;
case ADC_INSTALL_PDC:
/* Install the pendown interrupt callback function */
adccfgptr->pd_cbfunc = (PFV) arg;
break;
case ADC_INSTALL_EOS:
/* Install the end of sequence interrupt callback
function */
adccfgptr->eos_cbfunc = (PFV) arg;
break;
case ADC_SET_IDLE_CH:
/* Configure or reconfigure the ADC inputs used
during idle mode */
chcfgptr = (ADC_CH_CONV_T *) arg;
tmp = (ADC_SETTIME(chcfgptr->settle_clks) |
ADC_INPSEL(chcfgptr->inpc) |
ADC_INNSEL(chcfgptr->innc) |
ADC_REFP_SEL(chcfgptr->vrefp));
adcregsptr->adcidlehi = tmp;
/* Build and save the control bank low word register */
tmp = (ADC_REFN_SEL(chcfgptr->vrefn) |
chcfgptr->bias);
adcregsptr->adcidlelo = tmp;
break;
case ADC_SET_WMLEVEL:
/* Set ADC FIFO watermark (interrupt trip) level */
tmp = adcregsptr->adcgencfg & ~ADC_WM_MASK;
adcregsptr->adcgencfg = (tmp |
ADC_WM_SET((UNS_32) arg));
break;
case ADC_ADD_CHANNEL:
/* Add a conversion sequence entry */
chcfgptr = (ADC_CH_CONV_T *) arg;
status = adc_add_sequence_entry(chcfgptr, adccfgptr);
break;
case ADC_CHG_CHANNEL:
/* Changes a conversion sequence entry with the passed
key argument */
chcfgptr = (ADC_CH_CONV_T *) arg;
status = adc_chg_sequence_entry(chcfgptr, adccfgptr);
break;
case ADC_START_SAMP:
/* Starts an ADC sample */
adcregsptr->adcgencfg |= ADC_SSB_START;
break;
case ADC_SET_STATE:
/* Set sampling state */
if (arg == ADC_MODE_RESET)
{
/* Reset ADC controller and driver */
adc_default(adcregsptr);
/* Empty ring buffer and set conversion counter
to 0 */
adccfgptr->rx_head = adccfgptr->rx_tail = 0;
adccfgptr->conv_count = 0;
}
else if (arg == ADC_MODE_STOP)
{
/* Stop the ADC controller */
tmp = adcregsptr->adcpcr & ~ADC_PWM_MASK;
adcregsptr->adcpcr = (tmp | ADC_PWM_ALL_OFF);
}
else if (arg == ADC_SW_TRIGGERED)
{
/* ADC mode is polled/sw triggered */
/* Disable and clear ADC interrupts */
adcregsptr->adcie &= ~((UNS_32) arg &
(ADC_FIFO_OV_INT | ADC_WATERM_INT |
ADC_EOS_INT | ADC_PEN_INT | ADC_GLOBAL_INT));
adcregsptr->adcic = ((UNS_32) arg &
(ADC_EOS_CLR | ADC_PEN_CLR | ADC_BROWNOUT_CLR));
/* Standby mode */
tmp = adcregsptr->adcpcr & ~ADC_PWM_MASK;
adcregsptr->adcpcr = (tmp | ADC_PWM_STANDBY);
/* Enable triggered mode */
tmp = adcregsptr->adcgencfg & ~ADC_SSM_MASK;
adcregsptr->adcgencfg = (tmp | ADC_SSM_SSB);
}
else if (arg == ADC_PENDOWN_TRIGGERED)
{
/* An ADC sequence is started on a pendown
detection event */
/* Standby mode */
tmp = adcregsptr->adcpcr & ~ADC_PWM_MASK;
adcregsptr->adcpcr = (tmp | ADC_PWM_STANDBY);
/* Enable pendown triggered mode */
tmp = adcregsptr->adcgencfg & ~ADC_SSM_MASK;
adcregsptr->adcgencfg = (tmp | ADC_SSM_PEN);
}
else if (arg == ADC_PENDOWN_SW_TRIGGERED)
{
/* An ADC sequence is started on a pendown
detection event or software request */
/* Standby mode */
tmp = adcregsptr->adcpcr & ~ADC_PWM_MASK;
adcregsptr->adcpcr = (tmp | ADC_PWM_STANDBY);
/* Enable pendown triggered mode */
tmp = adcregsptr->adcgencfg & ~ADC_SSM_MASK;
adcregsptr->adcgencfg = (tmp | ADC_SSM_SSB_PEN);
}
else if (arg == ADC_CONTINUOUS)
{
/* Place ADC in run mode */
tmp = adcregsptr->adcpcr & ~ADC_PWM_MASK;
adcregsptr->adcpcr = (tmp | ADC_PWM_RUN);
/* Continuous sampling */
tmp = adcregsptr->adcgencfg & ~ADC_SSM_MASK;
adcregsptr->adcgencfg = (tmp | ADC_SSM_CONT);
}
else
{
/* Unknown mode */
status = SMA_BAD_PARAMS;
}
break;
case ADC_GET_STATUS:
switch (arg)
{
case ADC_RAWINT_ST:
/* Return raw interrupt statuses */
status = (INT_32) (adcregsptr->adcrawint &
(ADC_FIFO_OV_IRQ | ADC_WATERM_IRQ |
ADC_EOS_IRQ |ADC_PEN_IRQ |
ADC_BROWNOUT_IRQ));
break;
case ADC_INT_ST:
/* Return pending (enabled) interrupt
statuses */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -