使用的串口4空闲接收中断 + DMA,为什么只有在串口4的接收中断中打印输出才是完整,同时在调试watch1内也能看到USART4_RX_BUF数据和Usart4_Rec_Cnt 的接收动态,在外部main函数中调用Get_Picture()函数,用串口3却打印不出来,而且接收计数器Usart4_Rec_Cnt 也都为0(同样使用中断输出加黑标粗的代码)
void Get_Picture(void)
{
u8 tx = 0, rx = 0;
u8 senddata[7] = { 0x55, 0x48, 0x01, 0x33, 0x00, 0x02, 0x23}; //发送读数据协议55 48 01 32 00 02 23
usart4_send(senddata, 7); //发送7位读数据协议
u3_printf("CAM_TX:
");
for(tx = 0; tx < 7; tx ++)
{
u3_printf("%02X ",senddata[tx]);
}
u3_printf("
");
u3_printf("CAM_RX:
");
for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
{
u3_printf("%02X ",USART4_RX_BUF[rx]);
}
u3_printf("
");
}
void uart4_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_UART4_RX;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); //使能DMA传输
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);
USART_DeInit(UART4); //复位串口4
//UART4_TX PC10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC10
//UART4_RX PC.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PB11
//485EN PB.4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //内部上拉输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART4_SEND = U4SEND_DISABLE;
//Uart4 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(UART4, &USART_InitStructure); //初始化串口4
USART_ITConfig(UART4, USART_IT_IDLE, ENABLE); //开启空闲中断
USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE); //使能串口4的DMA接收
USART_Cmd(UART4, ENABLE); //使能串口
//DMA_RX相应的DMA配置
DMA_DeInit(DMA2_Channel3); //将DMA的通道5寄存器重设为缺省值 串口1对应的是DMA通道5
DMA_UART4_RX.DMA_PeripheralBaseAddr = (u32)&UART4->DR; //DMA外设ADC基地址
DMA_UART4_RX.DMA_MemoryBaseAddr = (u32)USART4_RX_BUF; //DMA内存基地址
DMA_UART4_RX.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取发送到内存
DMA_UART4_RX.DMA_BufferSize = USART4_REC_LEN; //DMA通道的DMA缓存的大小
DMA_UART4_RX.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_UART4_RX.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_UART4_RX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_UART4_RX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_UART4_RX.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
DMA_UART4_RX.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_UART4_RX.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA2_Channel3, &DMA_UART4_RX); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART4_Tx_DMA_Channel所标识的寄存器
DMA_Cmd(DMA2_Channel3, ENABLE); //正式驱动DMA传输
}
void UART4_RX_DMA_Enable(void)
{
DMA_Cmd(DMA2_Channel3, DISABLE ); //先停止DMA
DMA_SetCurrDataCounter(DMA2_Channel3, USART4_REC_LEN); //DMA通道的DMA缓存的大小
DMA_Cmd(DMA2_Channel3, ENABLE); //使能USART4 TX DMA2 所指示的通道
}
void UART4_IRQHandler(void) //串口4中断服务程序
{
#ifdef OS_TICKS_PER_SEC //如果时钟节拍数定义了,说明要使用ucosII了.
OSIntEnter();
#endif
//串口4空闲中断
if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)
{
/* 1.清除标志 */
USART_ClearITPendingBit(UART4, USART_IT_IDLE); //清除中断标志
/* 2.读取DMA */
USART_ReceiveData(UART4); //读取数据
Usart4_Rec_Cnt = USART4_REC_LEN - DMA_GetCurrDataCounter(DMA2_Channel3); //接收个数等于接收缓冲区总大小减已经接收的个数
/* 3.开启新的一次DMA接收 */
UART4_RX_DMA_Enable(); //重新使能DMA,等待下一次的接收
u3_printf("CAM_RX:
");
for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
{
u3_printf("%02X ",USART4_RX_BUF[rx]);
}
u3_printf("
");
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
最开始是有加Usart4_Rec_Cnt这个判断条件的,但打印前串口3获取Usart4_Rec_Cnt这个变量为0,而调试watch窗口为非0,有记录到接收数据个数,其他地方没有做Usart4_Rec_Cnt清0处理,Usart4_Rec_Cnt为0判断条件不成立,我才把判断条件先给去掉的。
u3_printf("接收数据长度:%d",Usart4_Rec_Cnt)
if(Usart4_Rec_Cnt)
{
u3_printf("CAM_RX: ");
一开始是有加Usart4_Rec_Cnt这个判断条件,但是发送请求帧回复都是 0,
u3_printf("CAM_RX: ");
for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
{
u3_printf("%02X ",USART4_RX_BUF[rx]);
}
u3_printf(" ");
一开始是有加Usart4_Rec_Cnt这个判断条件,但是发送请求帧回复都是 0,以至于判断条件不成立不打印,我才释放掉判断条件。但是这个过程在watch串口都是能看到Usart4_Rec_Cnt和USART4_RX_BUF在变化。
if(Usart4_Rec_Cnt)
{
u3_printf("CAM_RX: ");
for(rx = 0; rx < Usart4_Rec_Cnt; rx ++)
{
u3_printf("%02X ",USART4_RX_BUF[rx]);
}
u3_printf(" ");
}
你这个判断怎么可能有用呢
这一条判断只是在发送完之后, 检查了是否有接收到, 没有就退出
应该是类似这样的一条判断
while(!Usart4_Rec_Cnt);
一周热门 更多>