我有以下 snipper 来生成声音,在 while 循环中,我想动态更改它,以便在声音生成过程中创建不同频率的声音。
for(uint16_t i = 0; i < sample_N; i++)
{
dataI2S[i*2] = i*5000;
dataI2S[i*2 + 1] =i*5000;
}
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*2);
while (1)
{
ps = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*b);
b++;
if (b == 5)
b = 1;
if(ps){
generate();
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, ps);
} else {
stop();
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
它仅使用第一个 sample_N*b 值生成声音。它不会动态更改。
如何HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*b);动态更改?
void DMA1_Stream5_IRQHandler(void) {
if(x % 2 == 1)
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*2);
else
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S2, sample_N2*2);
x++;
HAL_DMA_IRQHandler(&hdma_spi3_tx);
Run Code Online (Sandbox Code Playgroud)
}
当您告诉控制器通过 DMA 传输数据时,它只会注册您的愿望(指令),并且在 HAL_I2S_Transmit_DMA 函数内部时不传输任何内容。
您的循环将进行多次迭代,同时控制器传输单个缓冲区(与您的代码执行并行)。
因此,在传输时告诉控制器传输新数据可能会导致副作用。
您需要注册中断处理程序,它会告诉您传输已完成。
然后您需要再次注册您的后续“愿望”以维持不间断的数据流。
通常在控制器传输数据时更改缓冲区中的数据是没有意义的。通常我们使用两个缓冲区来传输真实数据:
您可以从中断处理程序设置全局标志并在循环中检查它(并从您的循环启动后续 tx)或使用消息队列将消息从中断处理程序传递到您的循环中。
static void MX_I2S3_Init(void) {
...some code
hdma_spi3_tx.Instance = DMA1_Stream0;
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
void DMA1_Stream0_IRQHandler(void) {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, 1);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
207 次 |
| 最近记录: |