工具/软件:TI-RTOS
CCS 版本 7.1.0.00016
Simplink MSP432 SDK 版本1.30.00.40
大家好、
我正在 MSP-EXP432P401R LaunchPad 上使用 TI-RTOS 和 TI 驱动程序开发一个简单的音频项目。
我有3项任务:
第一个是 ADC 任务。 此任务在连续模式下初始化 ADCBuf 模块、采样频率为48kHz、然后此任务将被终止。 模拟信号将在后台采样、转换为微伏并存储到缓冲器中、让我将其称为 AudioBuffer_in[AUDIO_buffer_size]。 ADC 任务的优先级为3。
ADC 任务的源代码:
//=========== ADCtask.h ======================================== #ifndef SOURCEFILES_TASTS_ADCTASK_H_ #define SOURCEFILES_TASTS_ADCTASK_H_ //*以 Hz 为单位的 ADC 采样频率*/ #define ADC_SAMPLING_FREQ 48000 #endif /* SOURCEFILES_TASTS_ADCTASK_H_*/==================================================================================================================================================================================================================================================================================================================================================== ADCTask.c =========================== /*标准头文件*/ #include #include #include /* XDC 模块接头*/ #include #include #include /* TI-RTOS 头文件*/ #include #include #include /* TI 驱动程序标题*/ #include #include /*板接头*/ #include "Board.h" #include #include /* *私有变量 */ ADCBuf_handle adcBuf; ADCBuf_Params adcBuf_Params; ADCBuf_Conversion adcBuf_ContinuousConversion[2]; uint16_t SampleBufferOne[2][AUDIO_buffer_length]; uint16_t sampleBufferTwo[2][AUDIO_buffer_length]; // *函数声明 */ void adcTask_function (UArg0、UArg1 arg1); void adcBuf_callback (ADCBUF_Handle handle、ADCBUF_Conversion *转换、void *完整的 ADCBuffer、 uint32_t 完整通道); /* 初始化 ADC 线程。 */ void ADCTask_Init (void){ Task_handle adcTask; Task_Params adcTask_Params; ERROR_Block errorBlock; /*初始化驱动程序*/ ADCBuf_init (); /*初始化错误块*/ ERROR_INIT (错误块); /*创建主任务*/ Task_Params_init (&adcTask_Params); adcTask_Params.STACKSIZE = ADC_TASK_STACK_SIZE; adcTask_Params.priority = adc_task_priority; adcTask = Task_create ((Task_FuncPtr) adcTask_function、&adcTask_Params、&errorBlock); if (adcTask == NULL){ /*无法创建 ADC 任务*/ while (1); } }/* ADC 任务函数。 // void adcTask_function (UArg0、UArg0 arg1){ /*初始化 ADCBuf 参数*/ ADCBuf_Params_init (&adcBuf_Params); adcBuf_Params.samplingFrequency = ADC_SAMPLING_FREQ; adcBuf_Params.RecurrencedMode = ADCBuf_Recurrence_mode_continuous; adcBuf_Params.returnMode = ADCBuf_return_mode_callback; adcBuf_Params.callbackFxn = adcBuf_callback; /*打开 ADCBuf0 */ adcBuf = ADCBuf_open (Board_ADCBUF0、&adcBuf_Params); 如果(!adcBuf){ /* AdcBuf 未正确打开。 * while (1); } /*配置转换结构*/ adcBuf_ContinuousConversion[0].arg = NULL; adcBuf_ContinuousConversion[0].adcChannel = Board_ADCBUF0CHANNEL0; adcBuf_ContinuousConversion[0].samplpleBuffer = samplpleBufferOne[0]; adcBuf_ContinuousConversion[0].sampleBufferTwo = sampleBufferTwo[0]; adcBuf_ContinuousConversion[0].samplesRequestedCount = audio_buffer_length; adcBuf_ContinuousConversion[1].arg = NULL; adcBuf_ContinuousConversion[1].adcChannel = Board_ADCBUF0CHANNEL1; adcBuf_ContinuousConversion[1].samplpleBuffer = samplpleBufferOne[1]; adcBuf_ContinuousConversion[1].samplpleBufferTwo = sampleBufferTwo [1]; adcBuf_ContinuousConversion[1].samplesRequestedCount = audio_buffer_length; /*开始转换*/ if (ADCBuf_convert (adcBuf、adcBuf_ContinuousConversion、2)!= ADCBuf_STATUS_SUCCESS){ /*未正确启动转换过程。 * while (1); } }/* ADCBuf 回调函数。 // void adcBuf_callback (ADCBuf_handle、ADCBuf_Conversion *转换、void *完整的 ADCBuffer、uint32_t 完整的通道){ /*调整原始 ADC 值*/ ADCBuf_adjustRawValues (handle、completedADCBuffer、audio_buffer_length、completedChannel); /*将 ADC 值转换为微伏并将其保存到输入音频缓冲器中*/ ADCBuf_convertAdjustedToMicroVolts (Handle、completedChannel、completedADCBuffer、AudioBuffer_in[completedChannel]、AUDIO_buffer_length); }
第二个是主任务。 此任务首先初始化其他2个任务、然后进入无限 while 循环。 在 while 循环中、它获取 AudioBuffer_in 中的数据、处理数据并将处理的数据存储到另一个缓冲区 AudioBuffer_out[AUDIO_buffer_size]中。 之后、它将发送一个信标发布信号、通知第三个任务、即 PWM 任务、来完成它们的任务。 主任务的优先级为1。
主任务源代码:
//=================== MainTask.h ================================= #ifndef SOURCEFILES_TASKS_MAINTASK_H_ #define SOURCEFILES_TASKS_MAINTASK_H_ #include /*主任务优先级和以字节为单位的堆栈大小*/ #define MAIN_TASK_PRIORITY 1 #define MAIN_TASK_STACK_SIZE 1024 // PWM 任务优先级和以字节为单位的堆栈大小*/ #define PWM_TASK_PRIORITY 2 #define PWM_TASK_STACK_SIZE 1024 /* ADC 任务优先级和以字节为单位的栈大小*/ #define ADC_TASK_PRIORITY 3 #define ADC_TASK_STACK_SIZE 1024 //音频缓冲器长度*/ #define AUDIO_Buffer_length 1024 //全局变量*/ extern semaphore_handle 信号量; extern uint32_t AudioBuffer_in[2][AUDIO_buffer_length]; extern uint32_t AudioBuffer_out[2][AUDIO_buffer_length]; //初始化主任务*/ extern void MainTask_Init (void); #endif /* SOURCEFILES_TASTS_MAINTASK_H_*/ //=================== MainTask.c ================================= /*标准头文件*/ #include #include #include /* XDC 模块接头*/ #include #include #include /* TI-RTOS 头文件*/ #include #include #include /* TI 驱动程序标题*/ #include /*板接头*/ #include "Board.h" #include #include #include #include /* 全局变量 */ Semaphore_handle 信标; uint32_t AudioBuffer_in[2][AUDIO_buffer_length]; uint32_t AudioBuffer_out[2][AUDIO_buffer_length]; /* 私有变量。 // ////*回波效果变量*/ Echoect_Params Effect_Params ={5、200、2}; // *函数声明。 // void mainTask_function (UArg0、UArg0 arg1); // 初始化主线程。 */ void MainTask_Init (void){ Task_handle 维护任务; Task_Params mainTask_Params; ERROR_Block errorBlock; Semaphore_Params semaphore_Params; /*初始化驱动程序*/ GPIO_init(); /*初始化错误块*/ ERROR_INIT (错误块); /*创建主任务*/ Task_Params_init (mainTask_Params); mainTask_Params.STACKSIZE = main_task_stack_size; mainTask_Params.priority = main_task_priority; mainTask = Task_create ((Task_FuncPtr) mainTask_function、mainTask_Params、&errorBlock); if (mainTask == NULL){ /*创建主任务失败*/ while (1); } /*创建信标句柄*/ Semaphore_Params_init (&semaphore_Params); 信号量= Semaphore_create (1、Semaphore_Params、&errorBlock); if (信标=NULL){ /*无法创建信标对象*/ while (1); } }/* 主任务函数。 */ void mainTask_function (UArg0、UArg0 arg1){ /*初始化 ADC 任务*/ //ADCTask_Init(); /*初始化 PWM 任务*/ PWMTask_Init(); /*永久循环*/ while (1){ GPIO_TOGGLE (Board_GPIO_LED0); /*应用音频效果*/ EchoEffect_ApplyEffect (AudioBuffer_in[0]、AudioBuffer_out[0]、AUDIO_Buffer_length、&Effechoect_Params); EchoEffect_ApplyEffect (AudioBuffer_in[1]、AudioBuffer_out[1]、AUDIO_buffer_length、&Effechoect_Params); /*发布信标*/ Semaphore_post (信标); 睡眠(1); } }
我上面提到的第三个任务是 PWM 任务。 此任务首先初始化 PWM 模块、在其 while 环路中、它等待来自主任务的信标信号、同时通过调用信标挂起来阻止信号。 当信号进入时、它获取 AudioBuffer_out 中的数据、计算该缓冲区中每个值所需的占空比、然后更改 PWM 信号的占空比。 PWM 的频率为250kHz。 此任务的优先级为2。
PWM 任务的源代码:
//======================================== PWMTask.h ================================================ #ifndef SOURCEFILES_TASKS_PWMTASK_H_ #define SOURCEFILES_TASKS_PWMTASK_H_ //* PWM 频率(Hz)*/ #define PWM_FREQ 250000 /*初始化 PWM 任务。 */ extern void PWMTask_Init (void); #endif //* SOURCEFILES_TASKS_PWMTASK_H_*/ //=========================== PWMTask.c ========================================= /*标准头文件*/ #include #include #include /* XDC 模块接头*/ #include #include #include /* TI-RTOS 头文件*/ #include #include #include /* TI 驱动程序标题*/ #include #include /*板接头*/ #include "Board.h" #include #include /* *函数声明 */ void pwmTask_function (UARg arg0、UARg arg1); /* 初始化 PWM 线程。 */ void PWMTask_Init (void){ Task_handle pwmTask; Task_Params pwmTask_Params; ERROR_Block errorBlock; /*初始化驱动程序*/ PWM_init(); /*初始化错误块*/ ERROR_INIT (错误块); /*创建主任务*/ Task_Params_init (&pwmTask_Params); pwmTask_Params.STACKSIZE = PWM_TASK_STACK_SIZE; pwmTask_Params.priority = PWM_task_priority; pwmTask = Task_create ((Task_FuncPtr) pwmTask_function、&pwmTask_Params、&errorBlock); if (pwmTask = NULL){ /*无法创建 PWM 任务*/ while (1); } }/* PWM 任务函数。 // void pwmTask_function (UArg0、UArg0 arg1){ /* PWM 句柄和参数*/ PWM_Handle PWM[2]; PWM_Params pwmParams; /*初始化 PWM 参数*/ PWM_PARAMS_INIT (&pwmParams); pwmParams.idleLevel = PWM_IDLE_LOW; pwmParams.dutyUnits = PWM_Duty_Fraction; pwmParams.dutyValue = PWM_Duty_Fraction _MAX / 2; pwmParams.periodUnits = PWM_PERIOD_Hz; pwmParams.periodValue = PWM_FREQ; /*打开并启动 PWM[0]*/ PWM[0]= PWM_OPEN (Board_PWM0、&pwmParams); if (PWM[0]= NULL){ /*无法打开 PWM0 */ while (1); } PWM_START (PWM[0]); /*打开并启动 PWM[1]*/ PWM[1]= PWM_OPEN (Board_PWM1、&pwmParams); 如果(PWM[1]= NULL){ /*打开 PWM1失败*/ while (1); } PWM_START (PWM[1]); /*永久循环*/ while (1){ /*等待主任务发布信标*/ Semaphore_pend (Semaphore、BIOS_wait_forever); uint16_t i; 对于(i = 0;i < AUDIO_buffer_length;i++){ PWM_setDuty (PWM[0]、(uint32_t)((((float) AudioBuffer_out[0][i])/ 2500000)* PWM_Duty_Frite_MAX)); PWM_setDuty (PWM[1]、(uint32_t)((((float) AudioBuffer_out[1][i])/ 2500000)* PWM_Duty_Frage_MAX)); } GPIO_TOGGLE (Board_GPIO_LED1); } }
主任务将在 BIOS_start()调用之前初始化。 另外两个将在主任务函数中初始化。
问题是主任务、如果我初始化 ADC 任务、PWM 任务将无法正常工作。 如果我不这么做、主任务和 PWM 任务工作正常、主任务在 AudioBuffer_in 中获取数据(在本例中、所有值等于0)、处理数据并发送信标 POST 信号。 PWM 会立即接收信号、因为它具有更高的优先级。 PWM 任务执行其任务、并通过调用信标挂起而被阻止、而主任务再次运行、依此类推。 让我们看看 主任务函数中的 ADCTask_Init()行。 如果我将其注释掉、这意味着没有 ADC 任务、因此其他任务可以正常工作。
任何人请帮帮我。