打印
[开发资料]

【CW32L031CxTx StartKit评估板测评】ADC多通道驱动JoyStick游戏手柄

[复制链接]
250|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lulugl|  楼主 | 2023-10-8 21:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lulugl 于 2023-10-8 21:58 编辑

#申请原创#
CW32L031 内部集成一个 12 位精度、最高 1M SPS 转换速度的逐次逼近型模数转换器 (SAR ADC),最多可将 16 路模拟信号转换为数字信号。现实世界中的绝大多数信号都是模拟量,如光、电、声、图像信号等,都要由 ADC 转换成数字信号,才能由 MCU 进行数字化处理。
首先我们偿试单通道单次转换功能:
选用PA01为ADC输入脚。根据数据手册,PA01为通道1:


根据用户手册根据START位启动ADC的流程如下:

编写代码如下:
/**
* @brief ADC I/O初始化
*
*/
void ADC_PortInit(void)
{
    //打开GPIO时钟
    __RCC_GPIOA_CLK_ENABLE();
    //打开ADC时钟
__RCC_ADC_CLK_ENABLE();
    //set PA01 as AIN1 INPUT
//    PA01_ANALOG_ENABLE();
//PA00_ANALOG_ENABLE();
}
void getadc(void)
{
CW_GPIOA->ANALOG_f.PIN1 =1; //设置 ADC 通道对应的 GPIO 引脚为模拟功能
CW_ADC->CR0_f.EN = 1;//设置 ADC_CR0.EN 为 1,使能 ADC 模块;
while(!CW_ADC->ISR_f.READY) //查询等待 ADC_ISR.READY 位变为 1,等待 ADC 模块启动完成;
{
;
}
CW_ADC->CR0_f.MODE = 0;     //设置 ADC_CR0.MODE 为 0,选择单通道单次转换模式;
CW_ADC->CR0_f.REF = 3;      //配置 ADC_CR0.REF,选择 ADC 的参考电压源;11为VDD
//配置 ADC_CR0.SAM 及 ADC_CR0.CLK,设置 ADC 的采样速度及时钟选择;
CW_ADC->CR0_f.SAM = 0; //5 个 ADCCLK 时钟周期
CW_ADC->CR0_f.CLK = 7; //111:PCLK / 128
CW_ADC->CR1_f.CHMUX = 1;  //配置 ADC_CR1.CHMUX,选择待转换的通道;AN1;
CW_ADC->START = 1; //设置 ADC_START.START 为 1,启动 ADC 转换;
while(CW_ADC->ISR_f.EOC == 0)  //等待 ADC_ISR.EOC 变为 1,
{
;
}
// 读取 ADC_RESULT0 寄存器中的 ADC 转换结果;
valueAdc = (uint16_t)(CW_ADC->RESULT0);  //接3.3V最大值是B9B
}
/**
* @brief Main function of project
*
* @return int
*/
int main(void)
{
    //使用sysTick作为1ms
    InitTick(8000000);
  //配置ADC测试IO口
    ADC_PortInit();
LogInit();
    while (1)
    {
getadc();
printf("adc:%d\r\n",valueAdc);
SysTickDelay(100);
    }
}
编译下载到开发板后实现效果如下:

我们偿试多通道单次转换功能:
这里我们选取PA01、PA02为输入功能。根据数据手册,PA01、PA02分别为ADC输入的CH1、CH2两个通道。根据用户手册对多通道单次转换的摸述为:

转换的代码如下:
void getadcmore(void)
{
CW_GPIOA->ANALOG_f.PIN1 =1; //设置 ADC 通道对应的 GPIO 引脚为模拟功能
CW_GPIOA->ANALOG_f.PIN2 =1; //设置 ADC 通道对应的 GPIO 引脚为模拟功能
CW_ADC->CR0_f.EN = 1;//设置 ADC_CR0.EN 为 1,使能 ADC 模块;
while(!CW_ADC->ISR_f.READY) //查询等待 ADC_ISR.READY 位变为 1,等待 ADC 模块启动完成;
{
;
}
CW_ADC->CR0_f.MODE = 3;     //设置 ADC_CR0.MODE 为 3,选择序列连续转换模式;
CW_ADC->CR0_f.REF = 3;      //配置 ADC_CR0.REF,选择 ADC 的参考电压源;11为VDD
//配置 ADC_CR0.SAM 及 ADC_CR0.CLK,设置 ADC 的采样速度及时钟选择;
CW_ADC->CR0_f.SAM = 0; //5 个 ADCCLK 时钟周期
CW_ADC->CR0_f.CLK = 7; //111:PCLK / 128
CW_ADC->SQR0_f.ENS = 1;  //设置 ADC_SQR0.ENS 为 1,转换序列为SQR0~SQR1;
CW_ADC->SQR0_f.SQR0 = 1; //sQR0 为AN1
CW_ADC->SQR0_f.SQR1 = 2; //SQR1 为AN2
CW_ADC->ICR = 0;
CW_ADC->START = 1; //设置 ADC_START.START 为 1,启动 ADC 转换;
while(CW_ADC->ISR_f.EOS == 0)  //等待 ADC_ISR.EOS 变为 1,2个通道全部转换完成。
{
;
}
// 读取 ADC_RESULT0 寄存器中的 ADC 转换结果;
valueAdc0 = (uint16_t)(CW_ADC->RESULT0);  //提取PA01的转换值
valueAdc1 = (uint16_t)(CW_ADC->RESULT1);  //提取PA02的转换值
}
主函数修改为:
int main(void)
{
    //使用sysTick作为1ms
    InitTick(8000000);
  //配置ADC测试IO口
    ADC_PortInit();
LogInit();
    while (1)
    {
getadcmore();
printf("adc0:%d\r\n",valueAdc0);
printf("adc1:%d\r\n",valueAdc1);
SysTickDelay(100);
    }
}
下载后我们成功的获取到了两个通道的数据:

JoyStick游戏手柄的驱动:
游戏手机的X接PA01,Y接PA02。
修改主程序代码如下:
int main(void)
{
    //使用sysTick作为1ms
    InitTick(8000000);
  //配置ADC测试IO口
    ADC_PortInit();
LogInit();
    while (1)
    {
getadcmore();
printf("adc0:%d\r\n",valueAdc0);
printf("adc1:%d\r\n",valueAdc1);
if(valueAdc0<1900)
{printf("left\r\n");}
else if(valueAdc0>=1900 && valueAdc0<2730)
{
printf("middle\r\n");
}
else if(valueAdc0>=2740 && valueAdc0<4090)
{
printf("right\r\n");
}
else
{
printf("keyDown\r\n");
}
if(valueAdc1<1900)
{printf("down\r\n");}
else if(valueAdc1>=1900 && valueAdc1<2730)
{
printf("middle\r\n");
}
else if(valueAdc1>=2740 && valueAdc1<4090)
{
printf("up\r\n");
}
SysTickDelay(100);
    }
}

这样就成功的获取到了游戏手柄所在的位置了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

145

主题

715

帖子

9

粉丝