本帖最后由 yinlian 于 2015-7-27 00:05 编辑 最近在开发的一个案子,使用STM32F030C8T6 主芯片,需要用到STM32F030C8T6的串口与外设完成通讯和控制,现在遇到的问题是:接收没有问题,单独发送也没有问题,但是将接收到的信息转化为控制命令发送回去的时候,发现出程序不能产生中断,程序死在发送函数了:下面是源码,请大侠们帮忙看看问题出在哪里: static void USART1_Init_config() { GPIO_InitTypeDef GPIO_Init_Struct; NVIC_InitTypeDef NVIC_Init_Struct; USART_InitTypeDef USART_Init_Struct; //¶¨ÒåGPIO¡¢USART ³õʼ»¯½á¹¹Ìå RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //´ò¿ªUSART1¡¢GPIOB(USART1 TX/RX ¸´ÓÃÒý½Å)ʱÖÓ USART1_DMA_config(); //ÅäÖÃUSART1 µÄDMAͨµÀ£» GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_0); GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_0); GPIO_Init_Struct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF; GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_Level_3 ; GPIO_Init_Struct.GPIO_OType = GPIO_OType_PP; GPIO_Init_Struct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB,&GPIO_Init_Struct); //ÅäÖÃPB6 ¡¢PB7ΪUSART1 TX ¡¢RX£¨ÍÆÃâÊä³öģʽ£© NVIC_Init_Struct.NVIC_IRQChannel = USART1_IRQn; NVIC_Init_Struct.NVIC_IRQChannelPriority = 0x01; NVIC_Init_Struct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_Init_Struct); //ÅäÖÃNVICÖжÏUSART1 ÖÐ¶Ï USART_Init_Struct.USART_BaudRate = 57600; USART_Init_Struct.USART_WordLength = USART_WordLength_8b; USART_Init_Struct.USART_StopBits = USART_StopBits_1; USART_Init_Struct.USART_Parity = USART_Parity_No; USART_Init_Struct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; USART_Init_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_Init_Struct); USART_ITConfig(USART1, USART_IT_RXNE,ENABLE); USART_ITConfig(USART1, USART_IT_TXE,DISABLE); USART_Cmd(USART1, ENABLE); //ÅäÖÃUSART1 Ϊ57600¡¢8¡¢1¡¢ÎÞ È«Ë«¹¤Ò첽ͨѶ£» 上面的代码是,打开串口1中断,配置串口1为全双工异步通讯模式,(配置:57600、8、无、无、1) void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1,USART_IT_RXNE) == ENABLE) { USART1_RxData_buffer[USART1_ReadData_count] = USART_ReceiveData(USART1); USART1_ReadData_count++; if (USART1_ReadData_count == 1 && \ USART1_RxData_buffer[0] != 'A') { USART1_ReadData_count = 0; } else if (USART1_ReadData_count == 2 && \ USART1_RxData_buffer[1] != 'X') { USART1_ReadData_count = 0; } else if (USART1_ReadData_count == 3 && \ USART1_RxData_buffer[2] != 'X') { USART1_ReadData_count = 0; } if (USART1_ReadData_count >= 11) { USART1_Rx_Status = SET; USART1_RxData_buffer[USART1_ReadData_count] = '\n'; USART1_RxData_buffer[USART1_ReadData_count+1] = '\0'; USART1_ReadData_count = 0; } } //串口接收 if (USART_GetITStatus(USART1,USART_IT_TXE) == ENABLE) { USART_ITConfig(USART1,USART_IT_TXE,DISABLE); USART1_Busy = RESET; } } 上面的代码是串口中断应用函数,当发送寄存器为空时产生中断,清除串口忙标志,以便发送函数判断发送是否完成。 void USART1_Printf(uint8_t* String) { while (*String != '\0') { USART_SendData(USART1, (uint16_t)*String); USART_ITConfig(USART1,USART_IT_TXE,ENABLE); USART1_Busy = SET; while (USART1_Busy == SET) { Char_LED(ON); } String++; } USART_ITConfig(USART1,USART_IT_TXE,DISABLE); } 上面是串口发送函数,发送完成时由中断函数清除串口忙标志; 下载程序后出现的现象是:程序启动时串口能够发送数据,比如我在主程序写这样一行代码: USART1_Printf("power on\n"); 串口助手能够看到打印信息;说明发送中断是可以工作的;但是当收到串口发来的字符串,再将字符串原样返回的时候 ,程序进入死循环了。在串口助手上只能看到第一个字符,其他字符打印不出来;说明程序发送第一个字符后进入死循环;分析程序,应该是死在这句: while (USART1_Busy == SET) { Char_LED(ON); } 这个标志位是在串口中断函数中,清除的;难道没有产生串口中断????但是为什么这句:USART1_Printf("power on\n");能够打印出信息呢? 将发送改到串口2发送,收到的字符串能够原样返回。调试了两天,实在百思不得其解!!!难道STM32的串口不能同时使用发送和接收中断吗? 还望那位大侠能给小弟指点一二,不胜感激!!!! |
STM32F0 project.rar
下载4.94 MB, 下载次数: 136, 下载积分: ST金币 -1
å®æ´å·¥ç¨æ件
【STM32F0开发日志/评测/笔记】+互补PWM波的产生
STM32F030 PB14和PB15无法输出PWM求助
【STM32F030探索套件】序列之五 外部中断
【STM32F0开发日志---二】+ucosii.2.92移植在STM32F030
上传个STM32F0+5110+内部温度传感器的菜鸟实例
【STM32F030探索套件使用问题】STM32F030 SPI方式驱动ST7565LCD失败
求一份STM32F051 I2C驱动LCD 12864的例程
STM32F0 M0 向结构体赋值进入HardFault异常
STM32F0 ADC-DMA方式采集2路数据时出现问题
STM32F030C8T6,TIM16定时慢很多问题?
结贴,虽然不是你说的这个原因。但是还是非常感谢你的指点
解决问题后的代码如下:
void USART1_IRQHandler(void)
{
uint8_t Rx_Data_Buf = 0;
if (USART_GetFlagStatus(USART1, USART_FLAG_TC) == SET) //发送中断被触发
{
USART_ClearFlag(USART1, USART_FLAG_TC);
USART1_Busy = RESET;
USART2_String("T\n");
}
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) //接收中断被触发
{
Rx_Data_Buf = USART_ReceiveData(USART1);
if (Rx_Data_Buf != '\n')
{
USART1_RxData_buffer[Rx_count] = Rx_Data_Buf;
Rx_count++;
if (Rx_count == 1 && USART1_RxData_buffer[0] != 'A')
Rx_count = 0;
if (Rx_count == 2 && USART1_RxData_buffer[1] != 'X' )
{
if (USART1_RxData_buffer[1] == 'A' )
Rx_count = 1;
else
Rx_count = 0;
}
if (Rx_count == 3 && USART1_RxData_buffer[2] != 'X' )
{
if (USART1_RxData_buffer[2] == 'A' )
Rx_count = 1;
else
Rx_count = 0;
}
//以上过滤无效打印信息,只有AXX开头的字符串才认为是需要接收的模块命令;
}
if (Rx_Data_Buf == '\n' && Rx_count > 10)
{
USART1_RxData_buffer[Rx_count] = Rx_Data_Buf;
USART1_RxData_buffer[Rx_count+1] = '\0';
Rx_count = 0;
Rx_ReadData_Over = SET;
}
}
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) == SET) //接收溢出中断被触发
{
USART_ClearFlag(USART1, USART_FLAG_ORE);
USART2_Printf("USART1 ISR(ORE) = %b\n",USART1->ISR);
}
//USART2_Printf("USART1 ISR = %b\n",USART1->ISR);
}
就是把之前的 :USART_GetITStatus(USART1,USART_IT_RXNE) 修改为:USART_GetFlagStatus(USART1,USART_FLAG_RXNE);
根本原因就是对这两个库函数的功能没有搞清楚;USART_GetITStatus(USART1,USART_IT_RXNE)这个函数的功能是获取你设置了那些中断,因为函数返回的是CR1/CR2/CR3的相应标志位;而中断函数中需要查询的是当前是哪个中断产生,所以必须使用USART_GetFlagStatus(USART1,USART_FLAG_RXNE);因为所有的中断请求都是在ISR寄存器中;查看库函数,只有这个函数返回的是ISR寄存器的值。
新手接触STM32,走了很多弯路!!!并且STM32F030系列的编程参考手册没有中文的,我们这些英文不太好的新手 ,学起来相当费力啊!!!希望以后不要再走这样的弯路!!!!
已经验证,不会是这个原因,程序中有两个地方关闭发送寄存器为空中断,一个在中断函数里、一个是当所有字符发送完成,遇到“\0”结束发送循环后,关闭发送寄存器为空中断,因为发送寄存器为空中断标志位必须通过写发送寄存器来清除,我的程序不上在中断函数写发送寄存器的,所以必须在响应中断后关闭中断请求;在发送函数里先写发送寄存器清除标志位,在开发送寄存器空中断请求:如下代码:
while (*String != '\0')
{
USART_SendData(USART1, (uint16_t)*String);
USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
USART1_Busy = SET;
while (USART1_Busy == SET)
{
Char_LED(ON);
}
String++;
}
不然的话,程序会一直在响应中断,不能处理发送函数,造成程序死循环;
我在主循环中写这样一句:USART1_Printf("main run is ok\n");在没有通过串口助手发送字符串之前,一直可以看到程序不断打印出这个消息;如果通过串口发送一个字符串,程序返回我发送的字符串的第一个字符,然后就进入死循环了。
还是请再帮忙看看,是什么原因发送寄存器空中断没有响应?
{
while (*String != '\0')
{
USART_SendData(USART1, (uint16_t)*String);
USART_ITConfig(USART1,USART_IT_TC,ENABLE);
while(USART_GetITStatus(USART1,USART_IT_TC)==RESET)
{
Char_LED(ON);
}
// USART1_Busy = SET;
// while (USART1_Busy == SET)
// {
// Char_LED(ON);
// }
String++;
}
// USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
//¹Ø±Õ·¢ËÍÖжÏ
}
我不太懂你这里为什么用TXE不用TC,如果可以你改成这样试试
if (USART_GetITStatus(USART1,USART_IT_TXE) == ENABLE)
{
USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
USART1_Busy = RESET;
}
这个条件应该一直不会执行;
所以Busy一直为1吧
这样还是不好看,能把你的工程文件加上来吗
怎么上传附件呢?
第一次在论坛发帖,请多指教!!!
压缩包,添加附件
完整的工程文件已经附上, 请帮忙看看是什么问题造成一旦接收中断产生后,就不能产生发送中断了????在没有产生接收中断前,发送中断是可以正常工作的!!!
需要帮忙看看程序出现了什么问题,顶贴不能解决什么问题,反而有借机赚分的嫌疑
不懂的情况下,帮顶当然是赚分的!
不帮你顶,你的帖子2天就沉了,没人看了!
{
while (*String != '\0')
{
USART_SendData(USART1, (uint16_t)*String);
USART_ITConfig(USART1,USART_IT_TC,ENABLE);
while(USART_GetITStatus(USART1,USART_IT_TC)==RESET)
{
Char_LED(ON);
}
// USART1_Busy = SET;
// while (USART1_Busy == SET)
// {
// Char_LED(ON);
// }
String++;
}
// USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
//¹Ø±Õ·¢ËÍÖжÏ
}
我不太懂你这里为什么用TXE不用TC,如果可以你改成这样试试
非常感谢你的帮助,问题已经解决!!!