OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15340|回复: 3

STM32 串口2中断接收,串口1发送

[复制链接]

1

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2012-12-6
在线时间
0 小时
发表于 2013-12-24 14:47:40 | 显示全部楼层 |阅读模式
本人现在需要将stm32串口1中断接收到的数据,通过串口2发送出去,可是现在出现的情况是,每次从串口调试助手向串口1发送数据时,串口1只能将数据转发出一次,当串口1接收到第二帧数据时,串口2并不能将数据转发出来,
于是我开始怀疑是不是串口1进入一次中断以后就死在里面了,一直出不了中断。在网上我也看到有人说是溢出中断,于是加了防溢出中断的程序,可是还是不行。
单步调试,发现溢出中断标志位一直是0,所以不存在溢出中断。我怀疑是不是串口1的USART1->SR中TXE位为1导致,串口一直在中断程序中,出不去。
发现将串口1接收到的数据同时通过串口1和2发送出去,就可以了。(这时USART1->SR中TXE位就置0了,估计就不会再死在中断里了)
不知道有没有大神知道怎么回事,实际上我根本没有开串口1的发送中断,即使发送缓冲区空中断标志置1,也不应该进入中断啊,结果现在如果想接收多帧数据,必须将接收到的数据同时通过串口1和2发出来,
而我不需要串口1发送数据,郁闷呐!!!

每一帧数据都已0X0D,0X0A,结束
u8 USART_RX_STA=0;       // 是自己定义的一个接收状态标记
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目


求大神指教,小弟感激不尽。
附上代码;程序参考原子哥的,在此感谢!

int main(void)
{                

          Stm32_Clock_Init(9);//系统时钟设置
        delay_init(72);                //延时初始化
        uart_init(72,9600); //串口1初始化
        USART2_Init(36,9600);  
        LED_Init();
        KEY_Init();                                         
          while(1) 
        {
          u16 i;
            if((USART_RX_STA&0x80))
          {        
          for(i=0;i<(USART_RX_STA&0x3F);i++)
          {
                 
          USART1->DR=USART_RX_BUF;//如果删掉这一行,串口2就只会发送出来一帧数据,然后估计就死在串口接收的中断程序中了
          USART2->DR=USART_RX_BUF;
          delay_ms(2);
          }
          USART_RX_STA=0;
          
          }

        }                                                                                            
}

串口2配置
//初始化IO 串口2
//pclk1CLK1时钟频率(Mhz)
//bound:波特率          
void USART2_Init(u32 pclk1,u32 bound)
{                            
        RCC->APB2ENR|=1<<2;           //使能PORTA口时钟  
        GPIOA->CRL&=0XFFFF00FF;        //IO状态设置
        GPIOA->CRL|=0X00008B00;        //IO状态设置         
        RCC->APB1ENR|=1<<17;          //使能串口时钟          
        RCC->APB1RSTR|=1<<17;   //复位串口2
        RCC->APB1RSTR&=~(1<<17);//停止复位                      
        //波特率设置
        USART2->BRR=(pclk1*1000000)/(bound);// 波特率设置         
        USART2->CR1|=0X200C;          //1位停止,无校验位.
        USART2->CR3=1<<7;           //使能串口2的DMA发送
        UART_DMA_Config(DMA1_Channel7,(u32)&USART2->DR,(u32)USART2_TX_BUF);//DMA1通道7,外设为串口2,存储器为USART2_TX_BUF 
        USART2->CR1|=1<<8;            //PE中断使能
        USART2->CR1|=1<<5;            //接收缓冲区非空中断使能                    
        MY_NVIC_Init(2,3,USART2_IRQChannel,2);//组2,优先级2,3                                                                                           
}

串口1配置
#include "sys.h"
#include "usart.h"
#include "led.h" 
#include "delay.h"
#include "usart2.h"
//加入以下代码,支持printf函数,而不需要选择use MicroLIB          
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 

        int handle; 
        /* Whatever you require here. If the only file you are using is */ 
        /* standard output using printf() for debugging, no file handling */ 
        /* is required. */ 
}; 
/* FILE is typedef’ d in stdio.h. */ 
FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 

        x = x; 

//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
        while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
        USART1->DR = (u8) ch;      
        return ch;
}
#endif 

//////////////////////////////////////////////////////////////////
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误           
u8 USART_RX_BUF[64];     //接收缓冲,最大64个字节.每个字节都是8位,超出此空间大小则溢出,认为接收错误
u8 USART_TX_BUF[64]={'m','b','c','d','e','f'};         //发送缓冲
u8 USART_BUF[64];
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
//定义所有数据均以A结束。A作为结束标识
u8 USART_RX_STA=0;       //接收状态标记 是自己定义的一个接收状态寄存器            
void USART1_IRQHandler(void)//接收数据采用中断,将接收的数据存放在数组UART_RX_BUF[64];
{
                u8 res,i;
        USART1->CR1&=~(1<<8);    //PE中断禁止
                 //溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
        if(USART1->SR&(1<<3))
        {  
            
                USART1->SR&=~(1<<3);                        //读SR
                USART_ReceiveData(USART1);                                //读DR
        }         
   
        if(USART1->SR&(1<<5))//接收到数据
        {        
            USART1->SR&=~(1<<5);//清除RXNE标志位
        
                res=USART1->DR; 
                if((USART_RX_STA&0x80)==0)//接收未完成
                {
                        if(USART_RX_STA&0x40)//接收到了0x0d
                        {
                                if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else USART_RX_STA|=0x80;        //接收完成了 
                        }else //还没收到0X0D
                        {        
                                if(res==0x0d)USART_RX_STA|=0x40;
                                else
                                {
                                        USART_RX_BUF[USART_RX_STA&0X3F]=res;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收          
                                }                 
                        }
                }
                
                                                                                         
}

#endif                                                                                 
//初始化IO 串口1
//pclk2CLK2时钟频率(Mhz)
//bound:波特率
//CHECK OK
//091209
void uart_init(u32 pclk2,u32 bound)
{           
        float temp;
        u16 mantissa;
        u16 fraction;           
        temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分         将一个浮点型的数赋值给一个整型的数,会强制类型转换,省去小数部分
        fraction=(temp-mantissa)*16; //得到小数部分         
    mantissa<<=4;
        mantissa+=fraction; 
        RCC->APB2ENR|=1<<2;   //使能PORTA口时钟  
        RCC->APB2ENR|=1<<14;  //使能串口时钟 
        ////////////////////max232的RXD接的是PA9,TXD接的是PA10,在此将PA10配置成上拉输入:8;将PA9配置成复用推挽输出:B
        GPIOA->CRH&=0XFFFFF00F; 
        GPIOA->CRH|=0X000008B0;//IO状态设置
                  
        RCC->APB2RSTR|=1<<14;   //复位串口1
        RCC->APB2RSTR&=~(1<<14);//停止复位                      
        //波特率设置
        USART1->BRR=mantissa; // 波特率设置
        USART1->CR1=0x0000;         
        USART1->CR1|=0X200C;  //1位停止,无校验
        //USART1->CR1&=0X200C;  //1位停止,无校验位.
        //使能接收中断
        USART1->CR1|=1<<8;    //PE中断使能
        USART1->CR1|=1<<5;    //接收缓冲区非空中断使能

        MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级 
}
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2012-12-6
在线时间
0 小时
 楼主| 发表于 2013-12-24 14:48:22 | 显示全部楼层
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-12-24 23:57:53 | 显示全部楼层
直接在我们例程上修改都很好实现啊.
你的这个:
    USART1->CR1&=~(1<<8);    //PE中断禁止
                 //溢出-如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
        if(USART1->SR&(1<<3))
        {  
            
                USART1->SR&=~(1<<3);                        //读SR
                USART_ReceiveData(USART1);                                //读DR
        }    
去掉吧.

你在我们例程基础上修改,很容易实现啊
串口2初始化,不知道你为什么初始化了DMA.发送又没用DMA,有点莫名其妙.

串口2初始化,直接按串口1的来.
然后main函数的while循环改为:
  while(1)
{
if(USART_RX_STA&0x8000)
{    
len=USART_RX_STA&0x3FFF;//得到此次接收到的数据长度 
for(t=0;t<len;t++)
{
USART2->DR=USART_RX_BUF[t];
while((USART2->SR&0X40)==0);//等待发送结束

USART_RX_STA=0;
}else

}
}

就能实现你的功能了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-12-24 23:58:38 | 显示全部楼层
注意,这是战舰板例程.STA是16位的了,不是8位了!具体请看我们战舰板串口实验的说明.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-7 11:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表