직렬+DMA+남 은 중단 부정 확 한 데이터 수신 실현
5708 단어 STM32
우선 직렬 포트 의 설정 과정 은 일반적인 설정 과 기본적으로 일치 하지만,한 가지 설명 은 dma 를 사용 하여 정 해 지지 않 은 데 이 터 를 수신 하면 비교적 자주 사용 하 는 방법 은 빈 공간 을 이용 하여 중단 하 는 것 이다.그 러 니까 설정 할 때 RXNE 를 중단 시 키 지 마 세 요.
직렬 포트 초기 화 시 중단 되 는 설정
// RXNE IDLE
USART_ITConfig(USART3, USART_IT_TC,DISABLE);
USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
직렬 포트 초기 화 완료 후 dma 설정 진행
//DMA1
// ,
// -> /8 /
//DMA_CHx:DMA CHx
//cpar:
//cmar:
//cndtr:
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA
DMA_DeInit(DMA_CHx); // DMA 1
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // ,
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA DMA
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA x
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA x
DMA_Init(DMA_CHx, &DMA_InitStructure); // DMA_InitStruct DMA USART1_Tx_DMA_Channel
DMA_Cmd(DMA_CHx,ENABLE);
}
수신 부분의 설정 입 니 다.주의해 야 할 멤버 변 수 는 DMA 입 니 다.DIR,전송 방향 설정.외부 데이터 부터 직렬 외부 장치 까지 DMA 사용DIR_PeripheralSRC 는 dma 를 초기 화하 고 직렬 에서 외부 로 전송 하려 면 DMA 를 사용 합 니 다.DIR_PeripheralDST 로 dma 를 초기 화 합 니 다.따라서 두 채널 을 보 내 고 받 을 때 두 개의 함 수 를 사용 할 수 있 으 며 하나의 매개 변수 만 다 릅 니 다.물론 바 텀 드라이브 를 작성 할 때 이 성 어 를 입구 매개 변수 에 넣 을 수도 있 습 니 다.상부 프로그램 이 호출 할 때 방향 설정 을 입력 하면 됩 니 다.
다음은 인 터 럽 트 서비스 함수 입 니 다.저 희 는 남 은 인 터 럽 트 를 설정 합 니 다.즉,외부 장치 가 요청 을 한 후에 이 데 이 터 를 받 은 후에 발생 하 는 인 터 럽 트 입 니 다.따라서 RNXE 인 터 럽 트 처럼 하나씩 받 을 때마다 저장 할 필요 가 없 으 며,남 은 인 터 럽 트 가 생 겼 을 때 데 이 터 는 이미 받 아 들 였 습 니 다.데 이 터 는 DMA 와 외부 에 설 치 된 맵 을 설정 할 때의 배열 에 저 장 됩 니 다.그래서 우리 의 중단 임 무 는 이 데 이 터 를 버퍼 로 옮 겨 공급 용 프로그램 으로 사용 하 는 것 입 니 다.동시에 직렬 수신 완료 플래그 를 표시 합 니 다.
void RX3_IT_Handler(void)
{
uint16_t temp = 0;
uint16_t i = 0;
#ifdef OS_TICKS_PER_SEC // , ucosII .
OSIntEnter( );
#endif
//
if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
{
temp = USART_ReceiveData( USART3 );//
DMA_Cmd(DMA1_Channel3,DISABLE); // DMA
//
temp = RX3_Recv_Len - DMA_GetCurrDataCounter(DMA1_Channel3);
for (i = 0;i < temp;i++)
{
RX3_Buff[i] = RX3_Temp[i];
}
RX3_Point=temp;
RX3_Point|=0x80;
// DMA
DMA_SetCurrDataCounter(DMA1_Channel3,RX3_Recv_Len);
// DMA
DMA_Cmd(DMA1_Channel3,ENABLE);
}
__nop();
#ifdef OS_TICKS_PER_SEC // , ucosII .
OSIntExit( );
#endif
}
dma 전송 을 한 번 시작 합 니 다(주로 직렬 로 데 이 터 를 보 냅 니 다.직렬 dma 전송 채널 을 정확하게 설정 한 후에 호출 합 니 다)
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE ); // USART1 TX DMA1
DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);//DMA DMA
DMA_Cmd(DMA_CHx, ENABLE); // USART1 TX DMA1
}
직렬 dma 수신 을 열 고 직렬 초기 화 완료 후 호출 하면 dma 수신 이 완 료 됩 니 다.
void u3_dma_init(void)
{
// RXNE IDLE
USART_ITConfig(USART3, USART_IT_TC,DISABLE);
USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
MYDMA_Config(DMA1_Channel3,(u32)&USART3->DR,(u32)RX3_Temp,RX3_Recv_Len);//RX
// DMA
USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);
}
응용 인터페이스 함수:직렬 dma 에서 보 냅 니 다.만약 에 부정 확 한 데 이 터 를 보 내 면 데이터 의 끝 에 끝 표 지 를 추가 할 수 있 습 니 다.그러면 dma 는 해당 하 는 길이 의 데이터 만 보 낼 수 있 습 니 다.
void u3_dma_sendData(u8 *buff)
{
u8 i=0;
unsigned char* p_str;
p_str=buff;
//
//
while(*p_str != TXEND_SYMBOL || *( p_str + 1 ) != TXEND_SYMBOL){
p_str++;
if(i++>70){
MyPrintf("error, not found txend_symbol\r\
");
return ;
}
}
usart_dma_init(DMA1_Channel2,(u32)&USART3->DR,(u32)buff,i);//TX
USART_DMACmd(USART3,USART_DMAReq_Tx,ENABLE);
MYDMA_Enable(DMA1_Channel2);
while(1){
if(DMA_GetFlagStatus(DMA1_FLAG_TC2)!=RESET) // 4
{
DMA_ClearFlag(DMA1_FLAG_TC2);// 4
break;
}
DMA_GetCurrDataCounter(DMA1_Channel2);//
}
// MyPrintf("send done!\r
");
}
그 중 usartdma_init 함수 와 MYDMAConfig 는 방향 이라는 성어 변수 만 다 릅 니 다.여 기 는 더 이상 열거 하지 않 습 니 다.
직렬 수신 에 대해 서 는 상부 에 스 캔 함 수 를 쓸 수 있 고 수신 이 완 료 된 표지 위 치 를 계속 검사 할 수 있 습 니 다.
이로써 직렬 dma 의 송 수신 이 완료 되 었 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
STM32CubeIDE를 사용해 보자 How To STM32CubeIDE 일본어판 (11) I2C를 사용해 보자 4 Si7020+ssd1306편STM32CubeIDE를 사용해 보자 How To STM32CubeIDE 일본어판 (10) I2C를 사용해 보자 3 ssd1306편의 계속입니다. Nucleo 보드와 Si7020, SSD1306을 연결합니다. 이번에...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.