硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2386|回复: 6
收起左侧

[有问必答] 串口中断接发数据的问题

[复制链接]

3

主题

6

回帖

15

积分

新手上路

积分
15
发表于 2018-3-21 16:53:00 | 显示全部楼层 |阅读模式
本帖最后由 jason_lunt 于 2018-3-21 16:58 编辑

写了一个通过串口中断实现串口接收数据串,等接收完数据串后,将数据串通过串口输出。但是现在只能接收到第一个字节的数据,后面的数据丢失,不知道原因是什么,求各路大神指点迷津!!
源码如下,附件为工程文件

/**
  ******************************************************************************
  * @file    Project/STM32F10x_StdPeriph_Template/main.c
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */  

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include "stdlib.h"
#include "bsp_tim.h"
#include "bsp_gpio.h"
#include "bsp_adc.h"
#include "bsp_modbus.h"
#include "misc.h"
//函数声明
void LED_GPIO_Configuration(void);
void USART1_Configuation(void);
void LED_Blink(void);
void TIM2_USART1_NVICInit(void);
void Timer2_Init(void);

float Real_AdcValue;
//外部变量声明
extern uint16_t ADC_ConvertedValue;

u8 FLAG_EOC_ADC = 0;

u8 data_buff[2];

int fputc(int ch, FILE *f)
{
                /* 发送一个字节数据到USART1 */
                USART_SendData(USART1, (unsigned char) ch);
               
                /* 等待发送完毕 */
                while (!(USART1->SR & USART_FLAG_TXE));               
//                while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
                return (ch);
}

///重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
                /* 等待串口1输入数据 */
                while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

                return (int)USART_ReceiveData(USART1);
}


//=============================================================================
//文件名称:Delay
//功能概要:延时
//参数说明:nCount:延时长短
//函数返回:无
//=============================================================================

/***********
void Delay(uint32_t nCount)
{
        for(; nCount != 0; nCount--);
}
***********************/

//=============================================================================
//文件名称:main
//功能概要:主函数
//参数说明:无
//函数返回:无
//=============================================================================
int main(void)
{
        u16 j = 0;
        Modbus_Init();
        TIM2_USART1_NVICInit();
        LED_GPIO_Configuration();        
        USART1_Configuation();
        Timer2_Init();
        printf("the SystemCoreClock is %d\r\n",SystemCoreClock);
//        printf("this is a adc test printf demo\r\n");
    while (1)
        {
                //LED_Blink();
                if (Modbus.ReceiveFlag == 1)
                {
                        for (j = 0; j < Modbus.ReceiveCnt; ++j)
                        {
                                USART_SendData (USART1, Modbus.ReceiveBuff[j]);
                                while (USART_GetITStatus (USART1, USART_FLAG_TC) == RESET);                                 
                        }
                        Modbus.ReceiveCnt  = 0;
                        Modbus.ReceiveFlag = 0;
                }
               
    }
}


//=============================================================================
//文件名称:LED_GPIO_Configuration
//功能概要:GPIO初始化
//参数说明:无
//函数返回:无
//=============================================================================
void LED_GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);                                                  
//=============================================================================
//LED -> PC13
//=============================================================================                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
}


/* bsp_usart-------------------------------------------------------------*/
//定义函数对串口进行初始化
//1使能串口时钟和对应的I/O钟 2 配置串口的I/O
//3配置串口的工作模式 波特率 115200、数据位8位、奇偶校验位0、停止位1位、无硬件流控制
void USART1_Configuation(void)
{
        GPIO_InitTypeDef  GPIO_InitSturcture;
        
        USART_InitTypeDef USART_InitStructure;
//开启时钟
        RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1|
                                RCC_APB2Periph_GPIOA,ENABLE);

        //配置串口I/O
        
        GPIO_InitSturcture.GPIO_Pin    = GPIO_Pin_9;
        GPIO_InitSturcture.GPIO_Mode   = GPIO_Mode_AF_PP;
        GPIO_InitSturcture.GPIO_Speed  = GPIO_Speed_50MHz;

        GPIO_Init(GPIOA , &GPIO_InitSturcture);

        GPIO_InitSturcture.GPIO_Pin    = GPIO_Pin_10;
        GPIO_InitSturcture.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
        GPIO_Init (GPIOA ,&GPIO_InitSturcture);
        
//3配置串口的工作模式 波特率 115200、数据位8位、奇偶校验位0、停止位1位、无硬件流控制
        USART_InitStructure.USART_BaudRate   = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_Parity     = USART_Parity_No;
        USART_InitStructure.USART_StopBits   = USART_StopBits_1;
        USART_InitStructure.USART_Mode       = USART_Mode_Rx|USART_Mode_Tx;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_ITConfig ( USART1, USART_IT_RXNE, ENABLE);
        USART_Init (USART1, &USART_InitStructure);
        //串口使能
        USART_Cmd (USART1,ENABLE);
}
void LED_Blink(void)
{
        PBout(5)=1;        
//        printf("the led is off\r\n");
//        Delay_us (2000);  
        delay_ms(1000);
        PBout(5)=0;
//        printf("the led is on \r\n");
//        Delay_us(2000);
        delay_ms(1000);
}
void USART1_IRQHandler(void)
{
        u8 sbuff;
        if ( USART_GetITStatus (USART1, USART_IT_RXNE) !=RESET)
        {
                sbuff = USART_ReceiveData ( USART1);
               
                if (Modbus.ReceiveFlag == 1)
                {
                return;
                }
                Modbus.ReceiveBuff[Modbus.ReceiveCnt++] = sbuff;        
                Modbus.TimeOut = 0;
                if (PBin (5)==0)
                        {
                        PBout(5)=1;        
                        }
                else
                        PBout (5)=0;
                if (Modbus.ReceiveCnt == 1)
                {
                        Modbus.TimeRun = 1;
                }
        }
}
void TIM2_USART1_NVICInit(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1);//a bbb        
        
        NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn ;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init (&NVIC_InitStructure);
        
        //串口1中断配置
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_Init (&NVIC_InitStructure);
}
void TIM2_IRQHandler()
{
        if (TIM_GetITStatus (TIM2, TIM_IT_Update))
        {
                if (Modbus.TimeRun != 0)
                {
                        Modbus.TimeOut++;
                        if (Modbus.TimeOut >8)
                        {
                                Modbus.TimeRun = 0;
                                Modbus.ReceiveFlag =1;
                        }
                }
        
                TIM_ClearFlag (TIM2, TIM_FLAG_Update);
        }
}
void Timer2_Init(void)
{
        TIM_TimeBaseInitTypeDef tim_InitStructure;
        RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE);
        TIM_DeInit (TIM2);
        tim_InitStructure.TIM_Period =1000-1;
        tim_InitStructure.TIM_Prescaler = 72-1;
        tim_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        tim_InitStructure.TIM_CounterMode   = TIM_CounterMode_Up;
        TIM_TimeBaseInit (TIM2, &tim_InitStructure);
        TIM_ITConfig (TIM2,  TIM_IT_Update, ENABLE);
        TIM_Cmd ( TIM2, ENABLE);

}

/* end -- -----------------------------------------------------------*/




Sensor2 _test4.rar

1004.71 KB, 下载次数: 46

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106959
QQ
发表于 2018-3-21 17:15:15 | 显示全部楼层
把串口以外的东西全部注释掉,单独测试你串口中断的接收是否正常。
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2018-3-21 18:04:27 | 显示全部楼层
eric2013 发表于 2018-3-21 17:15
把串口以外的东西全部注释掉,单独测试你串口中断的接收是否正常。

你好,你的意思是不要检查什么接收完成标志之类的信息,通过在线调试的时候查看变量的值来检验串口接收是否正常,我理解的对吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106959
QQ
发表于 2018-3-21 18:07:26 | 显示全部楼层
jason_lunt 发表于 2018-3-21 18:04
你好,你的意思是不要检查什么接收完成标志之类的信息,通过在线调试的时候查看变量的值来检验串口接收是 ...

都可以的,主要是看你的串口是否可以正常使用。在楼主位,你不是说只能接收到第一个字节的数据么,所以单独测试下你的这个串口。
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2018-3-21 18:31:27 | 显示全部楼层
eric2013 发表于 2018-3-21 18:07
都可以的,主要是看你的串口是否可以正常使用。在楼主位,你不是说只能接收到第一个字节的数据么,所以单 ...

我把定时中断服务函数注释掉了,然后结果是能显示2个字节的数据,后面的也还是收不到,不知道是什么原因

在线调试变量显示

在线调试变量显示

串口助手发送数据

 串口助手发送数据

在线调试变量显示

在线调试变量显示
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2018-3-22 16:48:27 | 显示全部楼层
//                if (Modbus.ReceiveFlag == 1)
//                {
//                        for (j = 0; j < Modbus.ReceiveCnt; ++j)
//                        {
//                                USART_SendData (USART1, Modbus.ReceiveBuff[j]);
//                                while (USART_GetITStatus (USART1, USART_FLAG_TC) == RESET);                                 
//                        }
//                        Modbus.ReceiveCnt  = 0;
//                        Modbus.ReceiveFlag = 0;
//                }
                if (Modbus.ReceiveFlag == 1)
                {
                        for (j = 0; j < Modbus.ReceiveCnt; ++j)
                        {
                                Modbus.SendBuff[j] = Modbus.ReceiveBuff[j];                                                                 
                        }
                        for(j = 0 ;j < Modbus.ReceiveCnt;j++)
                        {
                                USART_SendData (USART1, Modbus.SendBuff[j]);

                                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
                        }
                        Modbus.ReceiveCnt  = 0;
                        Modbus.ReceiveFlag = 0;
                }
问题解决了,把上面屏蔽掉的程序,替换成下面的程序作为主循环的内容即可。只是有点奇怪,后者也只是把数据换了一个缓存区,
再重新发送,为什么后者就可以发送显示完整的信息,前者却只能显示第一个字节。希望各路大神能指点迷津。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106959
QQ
发表于 2018-3-23 01:27:56 | 显示全部楼层
jason_lunt 发表于 2018-3-22 16:48
//                if (Modbus.ReceiveFlag == 1)
//                {
//                        for (j = 0; j < Modbus.ReceiveCnt; ++j)

建议继续精简。测试正常了,然后逐步添加功能。
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-11 21:28 , Processed in 0.234223 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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