IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> GD32 定时器+一个IO实现SIF读取 -> 正文阅读

[嵌入式]GD32 定时器+一个IO实现SIF读取

参照下面文章,单线通讯—SIF通讯协议(一线通)案例二 作者Geek YANG,程序中有少许错误,移植过来后,有修改,比如数据的时间长度,校验方式,接收收据的处理等,最后成功实现。
注释有些没改过来。。

/*******************************************************************************
 *@时  间 : 2022-2-22
 *@摘  要 : 主程序文件
 *@芯  片 : GD32F103CBT6
 *										  -------------			
*******************************************************************************/

/*================================= Demo说明 ===================================
定时器 + 一个GPIO口进行通讯数据读取
==============================================================================*/


/* 包含的头文件 ---------------------------------------------------------------*/
#include <gd32f10x.h>
#include <gd32f103e_eval.h>
/* 宏定义 ---------------------------------------------------------------------*/
#define DATA_REV_PIN            gpio_input_bit_get(GPIOB,BIT(9))     //定义数据接收引脚(根据实际项目进行更改)

#define LOW                     0       //低电平
#define HIGH                    1       //高电平

#define SYNC_L_TIME_NUM         1100    //同步信号低电平时间:50ms = 50000us / 50us = 1000
#define SYNC_H_TIME_NUM_MIN     8      //同步信号高电平最小时间:500-100us = 400us / 50us = 8  
#define SYNC_H_TIME_NUM_MAX     12     //同步信号高电平最大时间:500+100us = 600us / 50us = 12

#define SHORT_TIME_NUM_MIN      9     //一个逻辑周期中短的时间最小值:500-50us = 450us / 50us = 9
#define SHORT_TIME_NUM_MAX      11    //一个逻辑周期中短的时间最大值:500+50us = 550us / 50us = 11

#define LONG_TIME_NUM_MIN       18    //一个逻辑周期中长的时间最小值:1ms-100us = 900us / 50us = 18
#define LONG_TIME_NUM_MAX       22    //一个逻辑周期中长的时间最大值:1ms+100us = 1100us / 50us = 22

#define LOGIC_CYCLE_NUM_MIN     26    //一个逻辑周期最小时间:1.5ms-200us = 1300us / 50us = 26
#define LOGIC_CYCLE_NUM_MAX     34    //一个逻辑周期最大时间:1.5ms+200us = 1700us / 50us = 34

#define HALF_LOGIC_CYCLE_MIN    13    //一个逻辑周期的1/2最小时间:750-100us = 650us / 50us = 13
#define HALF_LOGIC_CYCLE_MAX    17    //一个逻辑周期的1/2最大时间:750+100us = 850us / 50us = 17

#define END_SIGNAL_TIME_NUM     100   //结束信号电平时间:5ms低电平 + Nms高电平,实际检测5ms低电平就行,一帧数据发送完成后检测5ms低电平就代表完成了,不发数据的时候上拉电阻拉高了

#define REV_BIT_NUM             8     //接收的bit位个数,看是按字节接收还是按字接收,1字节=8bit,1字=2字节=16bit
#define REV_DATA_NUM            12    //接收的数据个数


/* 类型定义 -------------------------------------------------------------------*/
typedef enum
{
    INITIAL_STATE=0,            //初始状态,等待接收同步信号
    SYNC_L_STATE=1,             //接收同步低电平信号状态
    SYNC_H_STATE=2,             //接收同步高电平信号状态
    DATA_REV_STATE=3,           //读取数据码电平状态
    END_SIGNAL_STATE=4,         //接收结束电平信号状态
    RESTART_REV_STATE=5         //接收过程出错重新接收状态
}REV_STATE_e;                   //接收数据状态枚举

/* 变量定义 -------------------------------------------------------------------*/
unsigned char receive_state=0;      //接收数据状态
unsigned char receive_bit_num=0;    //接收的bit位个数
unsigned char receive_data_num=0;   //接收的数据个数

//接收数据缓存数组-用一个数组来缓存数据,51个数据字节
unsigned char receive_data_buf[REV_DATA_NUM]={0};
unsigned char receive_data[REV_DATA_NUM] = {0};

unsigned int  H_L_Level_time_cnt=0; //高低电平时间计数

uint8_t start_H_L_Level_timming_flag=0; //开始高低电平计时标记
uint8_t has_read_bit = 0;               //1-已经读取一个bit位
uint8_t check_OK = 0;                   //1-校验和正确,0-校验和失败
uint8_t read_success=0;                 //一帧数据是否读取成功,0-不成功,1-成功
uint8_t Pin_Old = 0;
uint8_t Pin_New = 0;
uint8_t Pin_Change_Flag = 0;
uint8_t BitFinish_Flag = 0;

/* 函数声明 -------------------------------------------------------------------*/
void GPIO_Init(void);               //GPIO初始化函数
void Timer0_Init(void);             //定时器0初始化函数
void Receive_Data_Handle(void);     //接收数据处理
void Check_Sum_Handle(void);        //校验和处理

/* 函数定义 -------------------------------------------------------------------*/
/*******************************************************************************
 *函数名称 : main
 *函数功能 : 主函数入口
 *输入参数 : void
 *输出返回 : void
*******************************************************************************/
void SIF_Handle(void)
{
    if (read_success == 1)              //如果成功读取一帧数据
    {
        //一帧数据接收成功后先根据协议要求进行校验和,验证数据的正确性
        Check_Sum_Handle();

        //如果数据正确,根据接收的数据进行分析获取需要的内容
        if (check_OK)
        {
            memcpy(receive_data, receive_data_buf, REV_DATA_NUM);
        }

        read_success = 0;               //读取一帧数据清0
    }
    
}

/*******************************************************************************
 *函数名称 : Timer0_isr
 *函数功能 : 定时器0中断处理函数
 *输入参数 : void
 *输出返回 : void
*******************************************************************************/

void TIMER1_IRQHandler(void)
{
    if(SET == timer_interrupt_flag_get(TIMER1, TIMER_INT_CH0)){
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH0);
        
        Pin_New = DATA_REV_PIN;
        
        if (start_H_L_Level_timming_flag==1)
        {
          H_L_Level_time_cnt++;     //高低电平维持时间计数变量
          
          Pin_Change_Flag = 0;
          BitFinish_Flag = 0;
          if(Pin_New != Pin_Old)
          {
            Pin_Change_Flag = 1;
            if(0 == Pin_New)
            {BitFinish_Flag = 1;}
          }
          Pin_Old = Pin_New;
        }   
        Receive_Data_Handle();      //接收数据处理,波特率自适应
        
        gd_eval_led_toggle(LED2);
    }
}
/*******************************************************************************
 *函数名称 : Receive_Data_Handle
 *函数功能 : 接收数据处理
 *输入参数 : void
 *输出返回 : void
*******************************************************************************/
void Receive_Data_Handle(void)
{
    switch (receive_state)                          //检测当前接收数据状态
    {
        case INITIAL_STATE:                         //初始状态,未接收到同步信息,进行同步判断
            if (DATA_REV_PIN == LOW)                //判断接收引脚的电平状态,当读到低电平时,开始计时
            {
                receive_bit_num = 0;                //重置bit位计数器
                receive_data_num = 0;               //重置接收数据个数
                H_L_Level_time_cnt = 0;             //高低电平计时变量清0
                start_H_L_Level_timming_flag = 1;   //开始高低电平计时
                receive_state = SYNC_L_STATE;       //进入读取同步低电平信号状态
                
                memset(receive_data_buf, 0 ,REV_DATA_NUM);
            }
            break;
        
        case SYNC_L_STATE:                          //在读取同步低电平信号期间
            if (DATA_REV_PIN == HIGH)               //同步信号低电平检测期间读到高电平
            {
                if (H_L_Level_time_cnt >= SYNC_L_TIME_NUM)//如果同步信号低电平时间>=SYNC_L_TIME_NUM
                {                                       //同步信号低电平时间要>=10ms
                    H_L_Level_time_cnt = 0;         //高低电平计时变量清0
                    receive_state = SYNC_H_STATE;   //进入读取同步信号高电平状态
                }
                else
                {
                    receive_state = RESTART_REV_STATE;      //进入重新接收状态  
                }
            }
            break;

        case SYNC_H_STATE:                          //在读取同步信号高电平期间
            if (DATA_REV_PIN == LOW)                //同步信号高电平检测期间读到低电平
            {
                //判断同步信号高电平时间是否在1ms±100us之间
                if (H_L_Level_time_cnt >= SYNC_H_TIME_NUM_MIN && H_L_Level_time_cnt <= SYNC_H_TIME_NUM_MAX)
                {
                    H_L_Level_time_cnt = 0;         //高低电平计时变量清0
                    receive_state = DATA_REV_STATE; //进入读取数据状态
                }
                else                                    
                {
                    receive_state = RESTART_REV_STATE;      //进入重新接收状态
                }
            }
            else            //如果在同步信号高电平检测期间,时间超过2ms±200us,认为超时
            {
                //判断时间是否超时 2ms±200us
                if (H_L_Level_time_cnt >= LOGIC_CYCLE_NUM_MAX)
                {
                     receive_state = RESTART_REV_STATE;      //进入重新接收状态
                }    
            }
            break;

        case DATA_REV_STATE:          //在读取数据码电平期间
            if ((has_read_bit==0) && (H_L_Level_time_cnt >= HALF_LOGIC_CYCLE_MIN && H_L_Level_time_cnt <= HALF_LOGIC_CYCLE_MAX)) 
            {
                receive_data_buf[receive_data_num] |= DATA_REV_PIN;
                
                has_read_bit = 1;
             }

            //如果已经读取一个bit位,且时间计数已经>=2ms±200us,说明一个逻辑周期过去了
            if ((has_read_bit==1) && (H_L_Level_time_cnt >= LOGIC_CYCLE_NUM_MIN && H_L_Level_time_cnt <= LOGIC_CYCLE_NUM_MAX))
            //if ((has_read_bit==1) && (1 == BitFinish_Flag))
            {
                H_L_Level_time_cnt = 0;             //高低电平计时变量清0
                has_read_bit = 0;                   //清0,读取下一个bit位
                receive_bit_num++;                  //接收的bit数++
                
                if (receive_bit_num == REV_BIT_NUM)   //如果一个字节8个bit位接收完成
                {
                    //receive_data[receive_data_num] = receive_data_buf[receive_data_num];
                    
                    receive_data_num++;             //接收的数据个数++
                    receive_bit_num = 0;            //接收bit位个数清0重新接收

                    if (receive_data_num == REV_DATA_NUM)   //如果数据采集完毕
                    {
                        receive_state = END_SIGNAL_STATE;   //进入接收结束低电平信号状态 
                    }  
                }
                else                                //如果一个字节8个bit位还没有接收完成
                {
                    //将接收数据缓存左移一位,数据从低bit位开始接收
                    receive_data_buf[receive_data_num] = receive_data_buf[receive_data_num] >> 1;
                }
            }        
            break;

        case END_SIGNAL_STATE:                              //在接收结束信号低电平期间
            if (DATA_REV_PIN == LOW)                       
            {
                if (H_L_Level_time_cnt >= END_SIGNAL_TIME_NUM)  //如果读到低电平时间>=5ms
                {
                        read_success = 1;                   //一帧数据读取成功
                        SIF_Handle();
                        start_H_L_Level_timming_flag = 0;   //停止高低电平计时
                        H_L_Level_time_cnt = 0;             //定时器计数值清0
           		receive_state = INITIAL_STATE;      //接收状态清0  
                }  
            }
            else    //结束信号低电平检测期间一直为低
            {
                //if (H_L_Level_time_cnt >= SYNC_L_TIME_NUM)  //如果读到低电平时间>=10ms,认为超时
                {                                           //一帧数据发送完成后需要间隔50ms才发送第二帧数据,期间肯定会被拉高
                    receive_state = RESTART_REV_STATE;      //进入重新接收状态
                }
            }
            break;

        case RESTART_REV_STATE:                     //重新接收数据状态
            start_H_L_Level_timming_flag = 0;       //停止高低电平计时
            H_L_Level_time_cnt = 0;                 //定时器计数值清0
            receive_state = INITIAL_STATE;          //接收状态清0    	
            break;
    }
}

/*******************************************************************************
 *函数名称 : Check_Sum_Handle
 *函数功能 : 校验和处理
 *输入参数 : void
 *输出返回 : void
*******************************************************************************/
void Check_Sum_Handle(void)
{
    unsigned char i = 0, checkByte = 0;
    unsigned long checkXor = 0;

    for ( i = 0; i < (REV_DATA_NUM ); i++)
    {
        checkXor = checkXor ^ receive_data_buf[i];
    }
    
    checkByte = (unsigned char)checkXor;

    if (checkByte == receive_data_buf[REV_DATA_NUM-1])  //校验和正确
    {
        check_OK = 1;           //标记校验成功
    }
    else
    {
        check_OK = 0;           //标记校验失败
    }
}

uint8_t * pGetSIFData(void)
{
  return receive_data;
}

最后版本的源文件附上:SIF.c

接收的数据,用串口发送出来,如下
在这里插入图片描述
完。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:49:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:58:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码