stm32根据时间间隔接收不定长数据代码

time.c

//time.c
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "adc.h"
#include "gate.h"
//#include"string.h"
extern u8 Receive_ok;
extern u8 RS485_RX_CNT;
extern u8 RS485_RX_BUF[20];
u8 d;//用于清除无效数据

//采样
//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr, u16 psc)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); ///使能TIM3时
  TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
  TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
  TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //初始化TIM3
  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //允许定时器3更新中断
  NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03; //抢占优先级1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; //子优先级3
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  失能定时器3
  TIM_SetCounter(TIM3, 0);
  TIM_Cmd(TIM3, DISABLE);
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM3, TIM_IT_Update)==SET) //溢出中断
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    TIM_Cmd(TIM3, DISABLE);

    //memset(RS485_RX_BUF, 0,RS485_RX_CNT);
    for(d=RS485_RX_CNT; d<20; d++)
    {
      RS485_RX_BUF[d] = 0 ;
    }

    RS485_RX_CNT = 0;//重要

    if ((RS485_RX_BUF[0] == 0xff) & (RS485_RX_BUF[5] == 0xed)) //数据帧头和帧尾正确时将Receive_ok置1,从而在main中执行
    {
      Receive_ok=1;
			LED1=!LED1;//DS1翻转
    }
 
  }

  TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志位
}

//---------------------------------------------------------------------//
//uart.c
#include "sys.h"
#include "usart6.h"
#include "led.h"
#include "time.h"
//
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
    #include "includes.h"					//ucos 使用
#endif


int t = 0;
u8 RS485_RX_CNT = 0;//缓冲区BUF当前存储的字节数
u8 RS485_RX_BUF[20];//存储上位机发来的命令buf,最大20
u8 Receive_ok = 0;//置1时代表从上位机接收到一帧数据


#if EN_USART6_RX   //如果使能了接收 	,对应代码最下方的endif

//初始化IO 串口6
//bound:波特率
void RS485_Init(u32 bound)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使能GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); //使能USART6时钟
    //串口6对应引脚复用映射
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6); //GPIOC6复用为USART6
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6); //GPIOC7复用为USART6
    //USART6
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //GPIOC6与GPIOC7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PA2,PA3
    //PC8推挽输出,485模式控制
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //GPIOG8
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //
    GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC8
    //USART1 初始化设置
    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(USART6, &USART_InitStructure); //初始化串口6
    USART_Cmd(USART6, ENABLE);  //使能串口 6
    USART_ClearFlag(USART6, USART_FLAG_TC);
    #if EN_USART6_RX
    USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);//开启相关中断
    //Usart6 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;//串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
    #endif
    RS485_TX_EN = 0;				//默认为接收模式
}


void USART6_IRQHandler(void)                	//串口6中断服务程序
{
    //modbus协议版本
    ///接收中断:开启定时器、读取数据并存储,清零计数器
    //定时器中断:数组计数器清零,标志位置位,关闭定时器
    //主函数:关闭定时器、标志位清零
    //9600波特率 一个字节1.4ms,3.5字符需要3.64ms,定义5ms
    //freemudbus
    u8 Res;

    if(USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
    {
        if(Receive_ok == 1)//正在处理时不接收
        {
            return;
        }

        Res = USART6->DR;	//读取接收到的数据
        TIM_SetCounter(TIM3, 0);
        TIM_Cmd(TIM3, ENABLE);   //开启计时器
        RS485_RX_BUF[RS485_RX_CNT] = Res ;
        RS485_RX_CNT++;
    }
}

#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntExit();
#endif

#endif


//RS485发送len个字节.
//buf:发送区首地址
//len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
void RS485_Send_Data(u8 *buf, u8 len)
{
    u8 t;
    RS485_TX_EN = 1;			//设置为发送模式

    for(t = 0; t < len; t++)		//循环发送数据
    {
        while(USART_GetFlagStatus(USART6, USART_FLAG_TC) == RESET); //等待发送结束

        USART_SendData(USART6, buf[t]); //发送数据
    }

    while(USART_GetFlagStatus(USART6, USART_FLAG_TC) == RESET); //等待发送结束

    //RS485_RX_CNT=0;
    RS485_TX_EN = 0;				//设置为接收模式
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好!要接收不定度的数据,您可以使用中断方式来实现串口数据接收。以下是一个基本的示例代码,用于接收帧头不定数据: ```c #include "stm32f4xx.h" #define BUFFER_SIZE 256 volatile uint8_t buffer[BUFFER_SIZE]; volatile uint16_t bufferIndex = 0; volatile uint8_t frameStarted = 0; void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { uint8_t data = USART_ReceiveData(USART2); if (frameStarted) { buffer[bufferIndex++] = data; // 检查帧尾的条件,例如检查某个特定字节作为帧尾 if (data == 0xXX) { // 帧尾检测成功,处理接收到的完整帧 // 处理完后可以重置bufferIndex和frameStarted,准备接收下一帧 bufferIndex = 0; frameStarted = 0; } else if (bufferIndex >= BUFFER_SIZE) { // 缓冲区溢出,处理异常情况 bufferIndex = 0; frameStarted = 0; } } else { // 检查帧头的条件,例如检查某个特定字节作为帧头 if (data == 0xYY) { // 帧头检测成功,开始接收数据 frameStarted = 1; buffer[bufferIndex++] = data; } } } } int main(void) { // 初始化串口 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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_Init(USART2, &USART_InitStructure); // 使能串口接收中断 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(USART2, ENABLE); // 配置串口中断优先级 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); while (1) { // 主循环中可以进行其他任务处理 } } ``` 在上面的示例代码中,我们使用了STM32的USART2串口,并使用了中断方式进行数据接收。在中断处理函数`USART2_IRQHandler`中,我们根据帧头和帧尾的特定字节进行帧的检测和处理。当检测到帧头时,开始接收数据并存储在缓冲区`buffer`中,当检测到帧尾时,表示接收到完整的帧,可以进行处理。 请注意,上述代码中的帧头和帧尾的特定字节需要您根据实际情况进行修改。另外,还需要根据您的具体需求调整缓冲区大小和处理接收到的完整帧的逻辑。 希望这个示例代码能对您有所帮助!如果有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值