历史上的今天

今天是:2024年11月14日(星期四)

2019年11月14日 | PIC16F1937-PC通讯协议

发布者:bobojrt 来源: 51hei关键字:PIC16F1937-PC  通讯协议 手机看文章 扫描二维码
随时随地手机看文章

main.c
/****************************************************************************/
/*                                                                          */
/*                Copyright (c) 2016, 老马工作室                            */
/*                     All rights reserved.                                 */
/*                                                                          */
/*      Email:pcwebmaster@163.com                                           */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c                                                       */
/* 版    本:Version 1.0                                                    */
/* 描    述:串行口中断带通讯协议测试                                       */
/* 主控芯片:PIC16F1937                                                                                                                */
/* 晶振频率:4MHz                                                                                                                */
/* 作    者:pcwebmaster(北极狼)                                            */
/* 函    数:                                                               */
/*                 system_init                                                     */
/*                 com_send_command                                                */
/*                 com_command_receive                                                                                                */
/*                        CalCRC16_1021                                                                                                        */
/*                        command_decoder                                                                                                        */
/*                        send_command                                                                                                        */
/* 测    试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15                        */
/* 测试现象:                                                                                                                                */
/* 历史记录:20016.02.19测试通过                                            */
/* 北极狼          20016-02-19     Creat Inital version. (Version 1.0)      */
/****************************************************************************/
#include "pic.h"
#include "comint.h"
__CONFIG(FOSC_INTOSC&CLKOUTEN_OFF&MCLRE_ON&WDTE_OFF);//&PWRTE_ON&BOREN_ON

#define _XTAL_FREQ      4000000L            //内部4MHz

//*******************************************************************//
//                          系统初始化
//*******************************************************************//
void System_Init(void)
{
        OSCCON = 0b01101000;            //内部4MHz 
        OSCTUNE= 0b00000000;            //出厂校准
        ADCON1 = 0b10110000;            //内部Frc Vref = VDD
        ADCON0 = 0b00010001;            //ADON = 1 As AN4

        TRISA  = 0b00100000;            //RA0-RA3输出、RA5输入
        ANSELA = 0b00100000;            //RA5 模拟输入  
                  
        TRISB  = 0b00001111;            //RB0-RB3触摸按键
        ANSELB = 0b00001111;            //4个触摸按键
        WPUB   = 0b00000000;            //无上拉

        IOCBP  = 0b00000000;            //关电平变化中断
        IOCBN  = 0b00000000;
        
        TRISD  = 0b00000000;            //PORTD输出
        ANSELD = 0b00000000;            //数字  I/O

        TRISC  = 0b10011000;            //串口 I2C

        TRISE  = 0b00000000;            //PORTE输出
        ANSELE = 0b00000000;            //数字  I/O
        WPUE   = 0b00000000;            //无上拉 
        
        LATA  = 0x00;
        LATB  = 0x00;
        LATC  = 0x00;
        LATD  = 0x00;
        LATE  = 0x00;
}
//*******************************************************************//
//                    TMR0定时初始化
//*******************************************************************//
void TMR0_Init(void)
{
        OPTION_REG = 0b11010011;        
        TMR0IF = 0;
        TMR0IE = 1;
}

//*******************************************************************//
//                             主程序部分
//*******************************************************************//

void main(void)
{
        INT8U *str="Hello World! nrSerial test normalnr";
        INT8U *end="nr";
        __delay_ms(10);
        System_Init();          //系统初始化
        CLRWDT();               //WDT看门狗
        TMR0_Init();            //TMR0初始化
        Serial_port_init();                //UART初始化
        PEIE = 1;               //外设中断允许
        GIE = 1;                //总中断允许
        buff_init();
        Send_String(str);
        Send_String(end);
        while (1)
        {
                com_command_receive();  
        }
}

COMINT.C
/****************************************************************************/
/*                                                                          */
/*                Copyright (c) 2016, 老马工作室                            */
/*                     All rights reserved.                                 */
/*                                                                          */
/*      Email:pcwebmaster@163.com                                           */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c                                                       */
/* 版    本:Version 1.0                                                    */
/* 描    述:串行口中断带通讯协议测试                                       */
/* 主控芯片:PIC16F1937                                                                                                                */
/* 晶振频率:4MHz                                                                                                                */
/* 作    者:pcwebmaster(北极狼)                                            */
/* 函    数:                                                               */
/*                 system_init                                                     */
/*                 com_send_command                                                */
/*                 com_command_receive                                                                                                */
/*                        CalCRC16_1021                                                                                                        */
/*                        command_decoder                                                                                                        */
/*                        send_command                                                                                                        */
/* 测    试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15                        */
/* 测试现象:                                                                                                                                */
/* 历史记录:20016.02.19测试通过                                            */
/* 北极狼          20016-02-19     Creat Inital version. (Version 1.0)      */
/****************************************************************************/
#include  
#include "comint.h"


uint8_t  pint_buf[MAX_RINTL];   /* 串口接收缓冲区       */
uint8_t  pint_read;             /* 串口缓冲区读指针     */
uint8_t  pint_write;            /* 串口缓冲区写指针     */
//uint8_t  psend_int;             /* 串口发送允许标志     */
uint8_t  serial_flag = 0;       /* 串口接收数据标志位   */


uint8_t  prec_buf[MAX_COMMAND_LEN];                /* 命令接收缓冲区    */
uint8_t  prec_num;                    /* 命令接收缓冲区字节数 */

uint8_t serial_lengthl = 0;           /* 消息命令长度低8位    */
uint16_t  serial_length = 0;          /* 消息命令长度16位     */

uint8_t ADDRESS[2]={ZU,ZHAN};               /* byte0:通讯组地址, byte1:开发板地址 */

//-----------------------------------------------------------------
// 串口初始化
//-----------------------------------------------------------------
void Serial_port_init(void)
{
        unsigned char BaudRate = 0;
        BaudRate = BAUDRATE;
        switch(BaudRate)
        {
                case 1: 
                                BRGH = 0;               //2400
                                SPBRG = 25;
                                break;
                case 2: 
                                BRGH = 0;               //4800 
                                SPBRG = 12;
                                break;
                case 3: 
                                BRGH = 1;               //9600
                                SPBRG = 25;
                                break;
                case 4: 
                                BRGH = 1;               //19200
                                SPBRG = 12;
                                break;
        }
        SYNC = 0;              // asynchronous
        SPEN = 1;              // enable serial port pins
        CREN = 1;              // enable reception
        TXEN = 1;         // enable Send
        SREN = 0;              // no effect
        TXIE = 0;         // Disable TX interrupts
        RCIE = 1;         // Enable  RX interrupts
}
//-----------------------------------------------------------------
// 串口发送一个字节
//-----------------------------------------------------------------
void com_send_command(char Onebyte)
{
        TXREG = Onebyte;
        while(TRMT);
        __delay_ms(1);//4M晶体最少需要1MS延时,??
}

//------------------------------------------------------------------
// (串口接收)中断程序(缓冲满时数据前移)
//------------------------------------------------------------------
void interrupt Serial_Port_Recv_ISR(void)
{
    uint8_t temp;
    uint8_t temp1;
        if(TMR0IE && TMR0IF)                   //4MHz  2.5ms
        {
                TMR0IF = 0;
                TMR0 = 0x65;
                CLRWDT();
        }        
        if(RCIE && RCIF)
        {
                temp1 = RCREG;                         //读取数据
                temp  = pint_write + 1; /* 判断是否可以写入 */
                if (temp == MAX_RINTL)
                {
                                temp=0;
                }
                if (temp != pint_read)
                {
                                pint_buf[pint_write] = temp1; /* 读取数据 */
                                pint_write = temp;
                }                        
        }        
}

void buff_init(void)
{
    uint8_t loop;
    loop = RCREG;   /* 清串口缓冲区   */
    for (loop=0; loop    {
        pint_buf[loop] = 0;
    }
}
////////////////////////////以上需要修改移植,以下直接移植并添加代码/////////////////////////////////////////////
//------------------------------------------------------------------
// 向PC机发送字符串
//------------------------------------------------------------------
void Send_String(char *str)
{
        while(*str)                  //检测str是否有有效
        {
                com_send_command(*str++);
        }
}
/* 串口接收数据处理 */
void com_command_receive(void)
{
    uint8_t var1,var4;
    uint16_t crc_data = 0;
    var4 = pint_read;

    if (var4 != pint_write)
    {
        var1 = pint_buf[var4];
        var4 = var4+1;
        if (var4 >= MAX_RINTL)
            var4=0;

        pint_read = var4;

        switch(serial_flag)
        {
            case 0: /*收到起始位*/
                if (var1 == SYN)
                {
                    serial_flag = 1;
//com_send_command(0x01); //测试
                }
                else
                {
                    serial_flag = 0;
                }
                break;

            case 1:/*收到起始位*/
                if (var1 == SYN)
                {
                    serial_flag = 2;
//com_send_command(0x02); //测试
                }
                else
                {
                    serial_flag = 0;
                }
                break;

            case 2:/*收到同步位*/
                if (var1 == STX)
                {
                    serial_flag = 3;
//com_send_command(0x03);//测试
                }
                else
                {
                    serial_flag = 0;
                }
                break;

            case 3: /*收到组地址*/
                if (var1 == ADDRESS[0])
                {
                    serial_flag = 4;
                    prec_num = 1;
                    prec_buf[0] = var1;
//com_send_command(0x04); //测试
                }
                else
                {
                    serial_flag = 0;
                }
                break;

            case 4:/*收到本机地址或者广播地址*/
                if ( (var1 == ADDRESS[1]) || (var1 == 0) )
                {
                    prec_num = 2;
                    prec_buf[1] = var1;
                    serial_flag = 5;
//com_send_command(0x05); //测试
                }
                else
                {
                    serial_flag = 0;
                }
                break;

            case 5:/*数据长度*/
                prec_num = 3;
                prec_buf[2] = var1;
                serial_lengthl = var1;
                serial_flag = 6;
//com_send_command(0x06);//测试
                break;

            case 6:
                prec_num = 4;
                prec_buf[3] = var1;
                serial_length |= var1;
                serial_length = ( (serial_length << 8) & 0xff00 ) + serial_lengthl + 3;
                serial_flag = 7;
//com_send_command(0x07);//测试
                break;

            case 7:
                prec_buf[prec_num] = var1;
                prec_num++;
                serial_length--;
                if (serial_length == 0)
                {
                    crc_data = CalCRC16_1021(prec_buf, prec_num - 2); /* 计算crc校验和(从组地址开始到ETX )*/

                    if ( ( (crc_data & 0x00ff) == prec_buf[prec_num - 2]) && ( ( (crc_data >>8) & 0x00ff) == prec_buf[prec_num - 1]) ) /* 校验和正确 */
                    {
                        prec_num = 1;
                        var1 = 0;

                        if ( (prec_buf[4] >= 0x31) && (prec_buf[4] <= 0x3b) ) /* 命令有效 */
                        {
                            if (prec_buf[1] != 0x00) /* 如果不是广播地址则回应ACK*/
com_send_command(0x49);//测试                                 msg_last_push(MSG_ACK,0);
//                                                                send_command(ACK); //测试    

                            command_decoder(); /* 如果校验和正确,则进行命令解码 */
                        }
                        else
                        {

send_command(NAK); //测试
                        }
                    }
                    else
                    {

send_command(NAK); //测试
                    }
                    serial_flag = 0;
                    prec_num = 1;
                }
                break;

            default:
                serial_flag = 0;
                prec_num = 1;
                break;
        }
    }
}
/* 命令解码子程序 */
void command_decoder(void)
{
//    uint8_t i = 0;

    if (prec_buf[4] == 0x31)       /* 设置报警阈值   */
    {                  
com_send_command(0x11);//测试
        return;
    }
    else if (prec_buf[4] == 0x32)  /* 请求报警阈值 */
    {
com_send_command(0x12);//测试?
        return;
    }
    else if (prec_buf[4] == 0x33)  /* 修改当前时间 */
    {
com_send_command(0x13);//测试
        return;
    }
    else if (prec_buf[4] == 0x34)  /* 请求当前时间 */
    {
com_send_command(0x14);//测试
        return;
    }
    else if (prec_buf[4] == 0x35)  /* 请求当前数据 */
    {
com_send_command(0xAA);//测试        
//__nop();
com_send_command(0x15);//测试
        return;
    }
    else if (prec_buf[4] == 0x36)  /* 请求看门狗信息*/
    {
com_send_command(0x16);//测试
        return;
    }
    else if (prec_buf[4] == 0x37)  /* 请求报警情况 */
    {
com_send_command(0x17);//测试
        return;
    }
    else if (prec_buf[4] == 0x38)  /* 配置设备地址 */
    {
        ADDRESS[0] = prec_buf[5];  /* 通讯组地址   */
        ADDRESS[1] = prec_buf[6];  /* 开发板地址   */
com_send_command(0x181);//测试
        return;
    }
    else if (prec_buf[4] == 0x39)  /* 请求设备地址 */
    {
com_send_command(0x19);//测试
        return;
    }
    else if (prec_buf[4] == 0x3a)  /* 控制模拟量输出 */
    {
com_send_command(0x1A);//测试?
        return;
    }
    else if (prec_buf[4] == 0x3b)  /* 控制开关量输出 */
    {
com_send_command(0x1B);//测试
        return;
    }
//                if (prec_buf[4] == 0x00)       /* 如果是广播地址  */
//    {                  
//                                com_send_command(SYN);
//                                com_send_command(0x00);
//                                com_send_command(SYN);
//        return;
//    }
}

/* 向PC主机发送消息帧,入口参数:消息类型 */
void send_command(uint8_t command)
{
    switch (command)
    {
        case ACK:
            com_send_command(SYN);
            com_send_command(SYN);
            com_send_command(ACK);
            break;

        case NAK:
            com_send_command(SYN);
            com_send_command(SYN);
            com_send_command(NAK);
            break;

        default:
            break;
    }
}

/*计算CRC校验和使用MTT(0X1021)
参数:
pBuff 为需计算CRC的缓冲区的头指针
BufferLen 缓冲区长度(以字节计)
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen)
{
    u_short i;
    uint8_t  j;
    u_short crc16 = 0;
    u_short mask = 0x1021;
    uint8_t *pByteBuffer;
    uint8_t tmpbyte;
    u_short calval;

    pByteBuffer = &x[0];

    for (i = 0; i < BufferLen; i++)
    {
        tmpbyte = *pByteBuffer;
        calval = tmpbyte << 8;
        for (j = 0; j < 8; j++)
        {
            if ((crc16 ^ calval) & 0x8000)
                crc16 = (crc16 << 1) ^ mask;
            else
                crc16 <<= 1;

            calval <<= 1;
        }
        pByteBuffer++;
    }
    return crc16;
}

COMINT.h
#ifndef __COMINT_H__
#define __COMINT_H__

#include
#include  

#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000UL   //4M晶振
#endif

#define BAUDRATE        3      //定义波特率 9600  N 8 1

#define INT8U   unsigned char
#define INT16U  unsigned int
#define uint8_t   unsigned char
#define u_short  unsigned int
#define uint16_t  unsigned int

#define ZU                        0x01                 /*组地址*///通讯地址修改这两项
#define ZHAN                0x02                 /*站地址*///通讯地址修改这两项

#define MAX_RINTL       16   /* 串口接收缓冲区长度   */
#define SYN           0x16   /* 通讯同步位*/
#define STX           0x02   /* 通讯起始位*/
#define ETX           0x03   /* 通讯结束位*/

#define ACK           0x06
#define NAK           0x15

#define MSG_ACK          2    /* 正确应答信息         */
#define MSG_NAK          3    /* 错误应答信息         */
#define MAX_COMMAND_LEN  16   /* 串口接受命令长度     */

extern char str_test[25]  ;
extern uint8_t  pint_read;             // 串口缓冲区读指针     */
extern uint8_t  pint_write;            // 串口缓冲区写指针
//extern uint8_t  data  psend_int;             // 串口发送允许标志    
extern uint8_t  pint_buf[MAX_RINTL];   // 串口接收缓冲区      
extern uint8_t serial_flag;              /* 串口接收数据标志位   */

extern uint8_t  prec_buf[MAX_COMMAND_LEN];/* 命令接收缓冲区 */        

/* 串口初始化*/
void Serial_port_init(void);
/* 串口发送一个字节 */
void com_send_command(char Onebyte);
void Send_String(char *str);// 向PC机发送字符串
/* 串口接收数据处理 */
void com_command_receive(void);
/* 串口接收初始化 */
void buff_init(void);

///* 串口接收一字节数据 */
//unsigned char UartReadChar(void); //reentrant
/*计算CRC校验和使用MTT(0X1021)
参数:
pBuff 为需计算CRC的缓冲区的头指针
BufferLen 缓冲区长度(以字节计)
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen);

/* 命令解码子程序 */
void command_decoder(void);
/* 向主机发送消息帧,入口参数:消息类型 */
void send_command(uint8_t command);

#endif

[1] [1]
关键字:PIC16F1937-PC  通讯协议 引用地址:PIC16F1937-PC通讯协议

上一篇:PIC单片机入门指南
下一篇:最后一页

推荐阅读

过去几年,因为5G、人工智能和自动驾驶等概念的兴起,其背后蕴含的大市场吸引了众多半导体芯片厂投身其中。尤其是正在努力发展自主集成电路产业链的中国,相关公司更是如雨后春笋般冒起。但由于这些新兴领域技术本身的原因,这就给相关进入者带来了更多的挑战,测试更是重中之重。 作为一个负责任的测试测量大厂,NI昨日在上海举办了“NI趋势展望报告2019...
11月13日,猎豹移动公布了2019年第三季度财报。在行业整体下滑及国内广告行业疲软的态势下,猎豹移动实现总收入9.2亿,其中移动娱乐业务收入达5.32亿,同比增长6.9%,业务收入达3475万,同比增长88%;同时本季度公司实现Non-Gaap净利润4.9亿,同比增长152%。 同时,猎豹移动董事长兼CEO傅盛在电话会议中宣布,猎户星空已经签署B轮融资协议,预计...
2018年1月份vivo全球首发了搭载屏幕指纹技术的X20 Plus屏幕指纹版,此后用上该技术的智能手机越来越多。图片来源:vivo官网据Omdia发布的数据显示,2019年屏幕指纹感测模组的出货量是2.28亿个,比起2018年的2950万个有了674% Y/Y的年增长,预计屏幕指纹模组于2020年的出货量,将继续会有显著的成长幅度,可望达到4亿个以上。图片来源:199it从Omdia发布...

史海拾趣

问答坊 | AI 解惑

LCD Scope 40MSPS

网上找到的一个示波器网站 http://www.eosystems.ro/…

查看全部问答∨

问个s3c2410的DMA和LCD问题,nXDreq,nXDACK应接到哪里去?找了个原理图没看明白

在应用层往LCD输出图像时,可以这样写: unsigned long *nPhysicalAddress = 0x30000000;(frame buffer address) 修改nPhysicalAddress 指向的内存即可 0x30000000是怎么得出的?和硬件连接有什么关系?我下了个原理图,好像不全,反正没看明白 ...…

查看全部问答∨

求救,自己定制系统不能显示中文??

奇怪,在pb5.0自己定制的系统不能显示中文,只能显示"_",但用mobile Hansheld作系统的话就能显示中文,什么回事呢? …

查看全部问答∨

SQL CE数据库的修改操作

我在wince6.0上开发sql ce 在建好一个数据库后,允许用户修改数据库中的内容,但是修改后却保存不了,数据库中还是原始内容。 大家有知道为什么吗? 相关代码如下(就是用了update方法): this.table2TableAdapter.Update(this.testdbDataSet1 ...…

查看全部问答∨

STM32的FLASH使能和禁止半周期访问对运行有什么区别吗

                                 如题…

查看全部问答∨

f2812AD转换波动很大,不知是什么原因?

用电位器输出一个电压值,从我watch窗口看到的ADCresult值都在变化,变化比较大。如0xabc0,b为都会能差4,帮忙分析一下可能那里设置不对。谢谢!…

查看全部问答∨

LM3S811使用心得之ADC

从参加抢LM3S811的活动后,每天都期待啊,终于在4.26的下午,顺风快递发来信息去取快递,其实已经料到是811到啦,好兴奋的跑到校门口外迎接顺风,领到包裹后,回寝室迫不及待的打开它,没错是811 。用811把我以前的LCD有重新驱动了起来,下面是我这 ...…

查看全部问答∨

对于一段教程的程式觉得有问题!

下面是一段简单的完整通讯程序,实现功能:将接受的数据原样送回。但是觉得南航教程中以下这段程序是不是少了一个子程,就是用于接收PC机发给MSP430的数据,并将接收到的数据放至发送缓存器? #include <msp430x44x.h>void main(void){WDT ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved