|
|
楼主 |
发表于 2026-9-15 08:39:36
|
显示全部楼层
这个学习项目实现的功能是通过串口发送指令VOLR***VOLL***FREQ******。也就是左声道音量3位数字,右声道音量3位数字,频率6位数字,单片机接收指令后,执行音量和频率值。
这是main.c的文件内容
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-09-05) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "tlv320aic23.h"
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
/************* 变量定义 **************/
u16 dac_L, dac_R; //左后声道DAC值
//======= 测试音正弦波相关 ==========
#define DEMO_16 2 //1: 使用16点正弦波表, 2: 使用32点正弦波表 (生成1kHz正弦波)
#if (DEMO_16 == 1)
// 16点正弦波表
u16 code T_SINE_16[16] = {
32768, 45014, 55395, 62332, 64768, 62332, 55395, 45014,
32768, 20522, 10141, 3204, 768, 3204, 10141, 20522
};
#else
// 32点正弦波表
u16 code T_SINE_32[32] = {
32768, 39011, 45014, 50547, 55395, 59376, 62332, 64153,
64768, 64153, 62332, 59376, 55395, 50547, 45014, 39011,
32768, 26525, 20522, 14989, 10141, 6160, 3204, 1383,
768, 1383, 3204, 6160, 10141, 14989, 20522, 26525
};
#endif
u16 TestTonePhase; // 测试音相位累加器(16位)
bit B_TestTone; // 测试音标志, 1:播放测试音
u16 ToneFreq; // 当前测试音频率 (Hz)
u16 ToneStepInc; // 相位累加步进值
//======= 命令解析相关(extern声明,定义在usblib.c) ==========
extern u8 ComBuf[64]; // 命令接收缓冲区
extern u8 ComLen; // 已接收命令长度
extern bit B_CmdReceived; // 收到完整命令标志
void I2S_config(void);
void SetHeadPhoneVolume(u16 vol);
void SetHeadPhoneVolumeL(u16 vol);
void SetHeadPhoneVolumeR(u16 vol);
void SetHeadPhoneVolumeLR(u16 volL, u16 volR);
void TestTone_Start(u16 freq); // 启动测试音
u16 StringToU16(u8 *str, u8 len); // 字符串转数字辅助函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
delay_ms(300);
AIC23_Init(); // void 函数,直接调用
delay_ms(50);
AIC32_InitSet(); // void 函数,直接调用
delay_ms(50);
SetHeadPhoneVolume(120); // 实际调用耳机音量设置
TestTone_Start(1000); // 启动1kHz测试音
P10 =0;
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
if(B_CmdReceived)
{
u16 volL, volR, freq;
u8 i;
bit B_VolLErr = 0; // 左声道音量越界标志
bit B_VolRErr = 0; // 右声道音量越界标志
bit B_FreqErr = 0; // 频率越界标志
volL = 120; // 默认左声道音量
volR = 120; // 默认右声道音量
freq = 1000; // 默认频率
// 解析命令字符串
i = 0;
while(i < ComLen)
{
// 解析VOLL(左声道音量, 后面3位数字)
if(ComBuf == 'V' && ComBuf[i+1] == 'O' &&
ComBuf[i+2] == 'L' && ComBuf[i+3] == 'L')
{
u8 len = 0;
i += 4;
// 读取3位数字
while(ComBuf >= '0' && ComBuf <= '9' && len < 3)
{
len++;
i++;
}
volL = StringToU16(&ComBuf[i-len], len);
// 越界检测:音量最大127
if(volL > 127)
{
B_VolLErr = 1; // 左声道音量越界
volL = 127; // 限制到最大值
}
}
// 解析VOLR(右声道音量, 后面3位数字)
else if(ComBuf == 'V' && ComBuf[i+1] == 'O' &&
ComBuf[i+2] == 'L' && ComBuf[i+3] == 'R')
{
u8 len = 0;
i += 4;
// 读取3位数字
while(ComBuf >= '0' && ComBuf <= '9' && len < 3)
{
len++;
i++;
}
volR = StringToU16(&ComBuf[i-len], len);
// 越界检测:音量最大127
if(volR > 127)
{
B_VolRErr = 1; // 右声道音量越界
volR = 127; // 限制到最大值
}
}
// 解析FREQ(频率, 后面6位数字, 单位Hz)
else if(ComBuf == 'F' && ComBuf[i+1] == 'R' &&
ComBuf[i+2] == 'E' && ComBuf[i+3] == 'Q')
{
u8 len = 0;
i += 4;
// 读取6位数字
while(ComBuf >= '0' && ComBuf <= '9' && len < 6)
{
len++;
i++;
}
freq = StringToU16(&ComBuf[i-len], len);
// 越界检测:频率最大16000Hz(采样率32K的一半)
if(freq > 16000)
{
B_FreqErr = 1; // 频率越界
freq = 16000; // 限制到最大值
}
if(freq < 20)
{
B_FreqErr = 1; // 频率低于最小值
freq = 20; // 限制到最小值
}
}
else
{
i++;
}
}
// 设置左右声道音量(仅当无越界错误时执行,或者始终执行的限制值)
SetHeadPhoneVolumeLR(volL, volR);
// 设置测试音频率
ToneFreq = freq;
ToneStepInc = (u16)((unsigned long)freq * 65536UL / 32000UL);
TestTonePhase = 0;
// 根据越界情况发送响应
if(B_VolLErr && B_VolRErr)
{
USB_SendData("VOLL/VOLR超出音量范围(0~127)\r\n", 28);
}
else if(B_VolLErr)
{
USB_SendData("VOLL超出音量范围(0~127)\r\n", 24);
}
else if(B_VolRErr)
{
USB_SendData("VOLR超出音量范围(0~127)\r\n", 24);
}
if(B_FreqErr)
{
USB_SendData("FREQ超出范围(20~16000Hz)\r\n", 24);
}
if(!B_VolLErr && !B_VolRErr && !B_FreqErr)
{
USB_SendData("CMD OK\r\n", 8);
}
// 清除命令标志和缓冲区
B_CmdReceived = 0;
ComLen = 0;
}
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramSpeed(1); //设置访问内部XDATA的速度(如果不使能DMA,可将参数设置为0)
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
//<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
// 在此添加用户预初始化代码
//<<AICUBE_USER_PREINITIAL_CODE_END>>
PORT1_Init(); //P1口初始化
PORT2_Init(); //P2口初始化
PORT3_Init(); //P3口初始化
PORT5_Init(); //P5口初始化
CLK_Init(); //时钟模块初始化
I2C_Init(); //I2C初始化
I2S_Init(); //I2S初始化
delay_ms(1);
USBLIB_Init(); //USB库初始化
delay_ms(1);
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//I2S_config();
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
USBLIB_WaitConfiged(); //等待USB完成配置
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//========================================================================
// 函数: void TestTone_Start(u16 freq)
// 描述: 启动测试音, 持续输出不停止
// 参数: freq - 测试音频率 (Hz)
// 返回: none.
// 版本: VER1.0
// 备注: 采样率32000Hz, 生成正弦波
// 相位累加器步进 = freq*65536/32000
//========================================================================
void TestTone_Start(u16 freq)
{
TestTonePhase = 0; // 相位清零
ToneFreq = freq; // 保存频率
ToneStepInc = (u16)((unsigned long)freq * 65536UL / 32000UL); // 计算步进
B_TestTone = 1; // 启动测试音
}
//========================================================================
// 函数: u16 StringToU16(u8 *str, u8 len)
// 描述: 将字符串转换为16位无符号整数(替代atoi)
// 参数: str - 字符串指针
// len - 数字长度
// 返回: 转换后的数值
//========================================================================
u16 StringToU16(u8 *str, u8 len)
{
u16 val = 0;
u8 i;
for(i = 0; i < len; i++)
{
if(str >= '0' && str <= '9')
{
val = val * 10 + (str - '0');
}
else
{
break;
}
}
return val;
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
这是完整的项目文件
TLVAIC23B学习.zip
(1.13 MB, 下载次数: 94)
|
|