2024年寒假练 - 基于SAMD21G17D综合开发平台的USB音量控制
该项目使用了SAMD21G17D综合开发平台,实现了USB音量控制的设计,它的主要功能为:滑动触摸条,调节电脑声音。
标签
2024年寒假练
USB音量控制
SAMD21G17D综合开发平台
冷月烟
更新2024-03-28
62

项目介绍

项目功能介绍

结合板子上的触摸滑条与USB通信,实现对电脑的控制

使用本板卡实现一个滑动控制器,用手指左右滑动时,电脑的音量可以变化。


设计思路

该项目主要有两部分组成:

  1. 触摸部分:通过板载的3段触摸条实现,这一部分硬禾提供了相关的文档,参照进行开发即可。
  2. USB部分:主要是实现一个HID音量控制报告描述符与相关数据上报代码即可,在官方手柄控制器例程上进行修改即可实现本次的功能。


硬件框图


软件流程图


硬件介绍

SAM D21 Curiosity Nano 评估套件

SAM D21 Curiosity Nano 开发板板载一个用于编程和调试的Nano调试器。Nano调试器是一个复杂的 USB 设备,由多个接口组成,如调试器、大容量存储设备、数据网关和虚拟接口、 数据网关和虚拟 COM 端口 (CDC)。板载 Nano 调试器接口与 MPLAB X IDE 配合使用时 可对 SAMD21G17D 进行编程和调试。DGI 可与逻辑分析仪通道一起使用,用于代码可视化程序流程。DGI GPIO 可使用数据展示台绘制图表。虚拟 COM 端口连接到 SAMD21G17D 上的 UART,提供了一种通过终端软件与目标应用程序通信的简便方法。

板卡特性:

  • 板载SAMD21G17D微控制器
  • 一个机械用户开关
  • 板载 Nano 调试器
    • 在 MPLAB X IDE 中识别电路板
    • 一个绿色电源/状态 LED
    • 编程和调试
    • 虚拟 COM 端口(CDC)
    • 一个逻辑分析器(DGI GPIO)
  • USB 供电
  • 可调目标电压
    • 由板载 Nano 调试器控制的 MIC5353 LDO 稳压器
    • 1.7V 至 3.6V 输出电压
    • 500 mA 最大输出电流(受环境温度和输出电压限制)


CURIOSITY NANO EVB扩展板


扩展板外设功能介绍:

  • 按键、电位器输入--------------以模拟信号的方式读取输入参数
  • 8路RGB灯珠显示------------通过发送数字信号,实现对每个LED的精确控制。
  • 0.96寸128*64OLED------------IIC接口通信,可直观显示各类传感器数据
  • 蜂鸣器输出-------------------以PWM信号驱动,可作为警报源
  • 电容触摸按键-------------------基于触摸函数库的电容触摸应用,并通过Data Visualizer 获取可视化触摸调试数据,可针对不同的触摸需求进行参数调整。
  • MCP9808数字温度传感器------可检测-40°C和+125°C之间的温度,具有用户可编程寄存器,可以为温度检测应用提供灵活性。这些寄存器支持用户可选的设置,例如关断或低功耗模式,以及温度报警窗口限制的规范和临界输出限制。
  • MCP7940N实时时钟/日历(RTCC)-----使用内部计数器跟踪小时、分钟、秒、天、数月、月年和数周的时间。警报可以在所有计数器上配置,包括数月。对于使用和配置,MCP7940N支持高达400 kHz的I2C通信。
  • 与SAMD21G17D MCU开发板的接口


实现的功能及图片展示

USB识别


主要代码片段及说明

外设配置


触摸配置



HID描述符

static const uint8_t hid_rpt0[] =
{
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
//???USAGE????????
0x09, 0xe9, // USAGE (Volume Up) //?????
0x09, 0xea, // USAGE (Volume Down)
0x09, 0xe2, // USAGE (Mute)
0x09, 0xcd, // USAGE (Play)
0x09, 0xb1, // USAGE (Pause)
0x09, 0xb5, // USAGE (Scan Next Track)
0x09, 0xb6, // USAGE (Scan Previous Track)
0x09, 0xb7, // USAGE(STOP) //????????????????count???????
0x75, 0x01, // REPORT_SIZE (1) //??????????HID Usage Tables?15?Consumer Page???
0x95, 0x08, // REPORT_COUNT (8) //
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};


触摸控制代码

voice_data = 0;
/* This means report can be sent*/
if(measurement_done_touch == 1u)
{
if(get_sensor_state(0) & KEY_TOUCHED_MASK)
{
GPIO_PB10_Clear();
}
else
{
GPIO_PB10_Set();
}

scroller_status = get_scroller_state(0);
scroller_position = get_scroller_position(0);

if ( 0u != scroller_status) {
printf("%d %d\r\n",scroller_status,scroller_position);
if(scroller_position > scroller_position_p)
{
voice_data = 1;
}
else if(scroller_position < scroller_position_p)
{
voice_data = 2;
}
scroller_position_p = scroller_position;
}
}


USB控制代码

void APP_USBDeviceHIDEventHandler
(
USB_DEVICE_HID_INDEX instanceIndex,
USB_DEVICE_HID_EVENT event,
void * pData,
uintptr_t context
)

{
APP_DATA * appDataObject = (APP_DATA *)context;

switch(event)
{
case USB_DEVICE_HID_EVENT_REPORT_SENT:

/* This means the mouse report was sent.
We are free to send another report */

appDataObject->isReportSentComplete = true;
break;

case USB_DEVICE_HID_EVENT_REPORT_RECEIVED:

/* This event is not used in this demo */

break;

case USB_DEVICE_HID_EVENT_SET_IDLE:

/* For now we just accept this request as is. We acknowledge
* this request using the USB_DEVICE_HID_ControlStatus()
* function with a USB_DEVICE_CONTROL_STATUS_OK flag */

USB_DEVICE_ControlStatus(appDataObject->deviceHandle, USB_DEVICE_CONTROL_STATUS_OK);

/* save Idle rate recieved from Host */
appDataObject->idleRate = *(uint8_t*)pData;
break;

case USB_DEVICE_HID_EVENT_GET_IDLE:

/* Host is requesting for Idle rate. Now send the Idle rate */
USB_DEVICE_ControlSend(appDataObject->deviceHandle,
& (appDataObject->idleRate),1);
/* On successfully reciveing Idle rate, the Host would acknowledge back with a
Zero Length packet. The HID function drvier returns an event
USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT to the application upon
receiving this Zero Length packet from Host.
USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT event indicates this control transfer
event is complete */

break;

default:
break;
}
}

/*******************************************************************************
Function:
void APP_USBDeviceEventHandler (USB_DEVICE_EVENT event,
USB_DEVICE_EVENT_DATA * eventData)

Summary:
Event callback generated by USB device layer.

Description:
This event handler will handle all device layer events.

Parameters:
None.

Returns:
None.*/

void APP_USBDeviceEventHandler(USB_DEVICE_EVENT event, void * eventData, uintptr_t context)
{
USB_DEVICE_EVENT_DATA_CONFIGURED * configurationValue;

switch(event)
{
case USB_DEVICE_EVENT_RESET:
case USB_DEVICE_EVENT_DECONFIGURED:

/* Device got deconfigured */

appData.isConfigured = false;
break;

case USB_DEVICE_EVENT_CONFIGURED:

/* Device is configured */

configurationValue = (USB_DEVICE_EVENT_DATA_CONFIGURED *)eventData;
if(configurationValue->configurationValue == 1)
{
appData.isConfigured = true;
/* Register the Application HID Event Handler. */

USB_DEVICE_HID_EventHandlerSet(appData.hidInstance,
APP_USBDeviceHIDEventHandler, (uintptr_t)&appData);
}
break;

case USB_DEVICE_EVENT_POWER_DETECTED:
/* Attach the device */
USB_DEVICE_Attach (appData.deviceHandle);
break;

case USB_DEVICE_EVENT_POWER_REMOVED:
/* Attach the device */
USB_DEVICE_Detach (appData.deviceHandle);
break;

case USB_DEVICE_EVENT_SUSPENDED:

break;

case USB_DEVICE_EVENT_RESUMED:
if(appData.isConfigured == true)
{
}
break;
case USB_DEVICE_EVENT_ERROR:
default:
break;

}
}


主代码

int main ( void )
{
//uint8_t uartLocalTxBuffer[100] = {0};
/* Initialize all modules */
SYS_Initialize ( NULL );
while ( true )
{
/* Maintain state machines of all polled MPLAB Harmony modules. */
SYS_Tasks ( );
touch_process();
}

/* Execution should not come here during normal operation */

return ( EXIT_FAILURE );
}


遇到的主要难题及解决方法

问题:USB一直不识别,怎么改都不行。

办法:底板typec只有一路D+D-另一路没连接,线也算同样的,所以不支持正反插,只有一个方向有效。


问题:改了代码编译没效果

办法:清除后全部编译解决。


未来的计划或建议

建议优化底板设计,或者提供更好的usb A转typec线,使板卡支持正反插功能。


附件下载
MyProject.zip
代码
团队介绍
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号