DMA1用于进行ADC数据的搬移,ADC配置为规则同步模式,同步采集两个通道,由TIM3触发,采样速度50k,16倍过采样,4bit右移,DMA1数据传输长度为200,开通半传输以及传输完成标志,半传输标志时开启LPUART的数据RX,使用DMA2进行数据传输,但是数据在传输时会存在串口数据不正确的情况
即便是降低采样的速度,输出数据依旧出现乱码的情况,两个DMA的总线之间应该是没有交集的,降速后也应该不会存在总线仲裁的问题,有没有大神知道原因
// DMA1配置
void DMA1_TRANS_INIT(void)
{
//通道1外设数据地址(adc双路转换结果)
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA_MULTI));
//通道1内存数据地址
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC_DUAL);
//通道1数据传输长度
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, ADC_DUAL_LENGTH/2);
//关闭半传输,打开传输完成中断,打开传输错误中断
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1);
//通道1使能
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
}
//DMA2
void DMA2_TRANS_INIT(void)
{
//设置外设地址
LL_DMA_SetPeriphAddress(DMA2,LL_DMA_CHANNEL_6,LL_LPUART_DMA_GetRegAddr(LPUART1,LL_LPUART_DMA_REG_DATA_TRANSMIT));
//关闭半传输,打开传输完成中断,关闭传输错误中断
LL_DMA_DisableIT_HT(DMA2, LL_DMA_CHANNEL_6);
LL_DMA_EnableIT_TC(DMA2, LL_DMA_CHANNEL_6);
LL_DMA_DisableIT_TE(DMA2, LL_DMA_CHANNEL_6);
//通道6使能
LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_6);
//使能发送DMA传输请求
LL_LPUART_EnableDMAReq_TX(LPUART1);
}
void LPUSART_DMA_SEND(uint32_t data,uint32_t len)
{
//等待上次传输完成
while(LL_LPUART_IsActiveFlag_TC(LPUART1) == RESET);
if(LL_LPUART_IsActiveFlag_TXE(LPUART1)!=RESET){
// 重新设置传输地址需要先关闭对应DMA通道
LL_DMA_DisableChannel(DMA2,LL_DMA_CHANNEL_6);
LL_DMA_SetMemoryAddress(DMA2,LL_DMA_CHANNEL_6,data);
//设置传输长度
LL_DMA_SetDataLength(DMA2,LL_DMA_CHANNEL_6,len);
LL_DMA_EnableChannel(DMA2,LL_DMA_CHANNEL_6);
}
}
#define ADC_DUAL_LENGTH 200
__align(8) uint16_t ADC_DUAL[ADC_DUAL_LENGTH];
void main()
{
while(1){
if(dma_tc_status == 1) {
dma_tc_status = 0;
LPUSART_DMA_SEND((uint32_t )&ADC_DUAL[ADC_DUAL_LENGTH/2],ADC_DUAL_LENGTH);
}
if(dma_ht_status == 1) {
dma_ht_status = 0;
//debug("\r");
while(LL_LPUART_IsActiveFlag_TC(LPUART1) == RESET);
LL_LPUART_TransmitData8(LPUART1, 13);
LPUSART_DMA_SEND((uint32_t )&ADC_DUAL[0],ADC_DUAL_LENGTH);
}
}
}
//中断配置
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if(LL_DMA_IsActiveFlag_TC1(DMA1) == 1)
{
LL_DMA_ClearFlag_TC1(DMA1);
dma_tc_status = 1;
receive_number++;
}
if(LL_DMA_IsActiveFlag_HT1(DMA1) == 1)
{
LL_DMA_ClearFlag_HT1(DMA1);
dma_ht_status = 1;
}
if(LL_DMA_IsActiveFlag_TE1(DMA1) == 1)
{
LL_DMA_ClearFlag_TE1(DMA1);
dma_te_status = 1;
}
/* USER CODE END DMA1_Channel1_IRQn 0 */
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
/**
* @brief This function handles DMA2 channel6 global interrupt.
*/
void DMA2_Channel6_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Channel6_IRQn 0 */
if(LL_DMA_IsActiveFlag_TC6(DMA2)!=RESET)
{
LL_DMA_ClearFlag_TC6(DMA2);
}
/* USER CODE END DMA2_Channel6_IRQn 0 */
/* USER CODE BEGIN DMA2_Channel6_IRQn 1 */
/* USER CODE END DMA2_Channel6_IRQn 1 */
}
|
串口的传输速率与ADC的采样速率(50K)比是相当慢,所以建议将采样速率降至100HZ一下试试。 或者改为手动触发使能DMA(DMA配置为NORMAL模式)。
我推荐,您加一个DMA通道做内存TO内存,估计您这个问题就解决了
建议两部分功能分开调,正常之后在合并到一起。