2019-09-18 15:57:36 snowmcu20132514 阅读数 251
  • 串口通信和RS485-第1季第13部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第13个课程,主要讲解了串行通信UART及其扩展RS485。本课程很重要,因为串口通信是我们接触的早也简单的通信方式,是后续继续学习SPI、I2C甚至USB、网络通信等的基础,大家务必认证对待完全掌握。

    6005 人正在学习 去看看 朱有鹏

在用单片机接收串口数据时,当接收数据不定长时 ,需要判断出何时接收完成,之前我写的一个文章是在QT中处理如何判断接收完成的,在单片机中的思路其实是一样的,只不过在QT中实例化了一个定时器,在未超时接收到数据时再重新定时,到接收完成不再接收时,达到超时时间,之后去处理相关的数据包,可以参考这个链接:
https://blog.csdn.net/snowmcu20132514/article/details/100739937。
在单片机中,我在STM32的单片机中这样做,有点问题,因为我用的是库开发,我并未找到怎么重新加载计数器的计数值。因此,我将定时的计数更新中断设置成了1ms,我的数据帧的长度是10个字节,115200的波特率,接收完成大概在1ms,我把超时时间设置为5ms,5ms没更新超时就认为接收完成了,之后就可以去解析数据包,从数据包中的数据正确的数据帧。主要是两个部分:
其一:串口中断,设置接收一个字节就进入中断一次,如果进入中断就重新设置超时时间为5ms,这样只要进入接收中断,那么超时时间就一直为5ms,并将接收的数据放入缓存,可以是数据或者队列,并设置一个全局变量设置串口在接收状态;
其二 :定时器更新中断,设置为1ms更新一次,如果串口在接收状态,每次将超时时间递减一,如果递减到0,说明已经超时,认为串口接收完成了,将前面设置的的全局变量设置为非接收状态,此时,就可以将这个数据包拿去解析了。

2008-11-25 13:42:00 AresGod 阅读数 1110
  • 串口通信和RS485-第1季第13部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第13个课程,主要讲解了串行通信UART及其扩展RS485。本课程很重要,因为串口通信是我们接触的早也简单的通信方式,是后续继续学习SPI、I2C甚至USB、网络通信等的基础,大家务必认证对待完全掌握。

    6005 人正在学习 去看看 朱有鹏
 
GPS串口数据接收程序实例


摘 要:目前GPS(全球定位系统)定位应用市场日趋成熟,正在进入应用的高速发展时期。本文以一款EverMore公司的GM-X205GPS接受模块为例,介绍了其数据格式,以及应用PIC16F874单片机RS232串口进行数据接收的程序。
1、 GPS应用简介
    近年来GPS系统,已经在大地测绘、海上渔用、车辆定位监控、建筑、农业等各个领域得到广泛应用。从九十年代我国引进GPS定位技术开始,经过十多年的市场培育,GPS定位应用进入了发展的最好时机,未来十年基于GPS的应用将会改变我们的生活和工作方式。
    目前市场上的大部分GPS接受模块都是通过RS232串口与MCU进行数据传输的。这些数据包括经度、纬度、海拔高度、时间、卫星使用情况等基本信息。开发人员再依据这些基本数据,进行数据处理来完成整套的定位系统软件。
    2、 GM-X205模块数据格式
    在进行数据接受编程之前,先介绍一下该模块的数据格式。它支持NMEA-0183输出格式。信息如下:
    GGA位置测定系统定位资料(Global Positioning System Fix Data)
    GSV 导航卫星资料(GNSS Satellites in View)
    RMC导航卫星特定精简资料(Recommended Minimum Specific GNSS Data)
    VTG 方向及速度等相关资料(Course Over Ground and Ground Speed)
    由于文章篇幅问题,笔者在这里只以接收GGA数据为例,格式如下:
    $GPGGA,hhmmss,dddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,M,x.x,xxxx*CS
    例:$GPGGA,033744,2446.5241,N,12100.1536,E,1,10,0.8,133.4,M,,,,*1F
说明见表:

区域
名称
单位
说明
1
信息ID
$GPGGA
 
GGA协议开始
2
UTC时间
033744
 
hhmmss
3
纬度
2446.5241
 
dddmm.mmmm
4
南/北半球指示
N
 
N=north ; S=south
5
经度
12100.1536
 
dddmm.mmmm
6
东/西半球指示
E
 
E=east ; W=west
7
定位指示
1
 
0 =未定位
1=定位SPS模式
2=定位DGPS, SPS模式
8
应位卫星数
10
 
00-12
9
HDOP
0.8
 
10
海拔高度
133.4
 
11
海拔高度单位
M
 
12
WGS84水准面划分
 
 
 
13
WGS-84水准面划分单位
 
 
 
14
累计GPS数据微分
 
 
本模块中不可用
15
参考工作站ID
 
 
本模块中不可用
16
校验位
*1F
 
 

上面例子中,我们可读出位置信息:北纬24度46.5241分,西经121度00.1536分
                                格林威治时间:3点37分44秒
3、 PIC16F874数据接收程序
笔者在系统中把接收到的数据处理后,显示到图形液晶屏上。限于篇幅在这里只给出数据接收部分程序,并且只接收经度和时间信息,并且给出格林威治时间转换为北京时间的转换函数。其他数据接收程序类似。
;**********************************************************
;         THIS IS A GPS RECEIVER PROGRAM                  *
;**********************************************************
         LIST P=16F874
         INCLUDE P16F874.INC       
;*******寄存器定义 ********************
TEMP1     EQU    0X27
W_TEMP    EQU    0X54         
STATUS_TEMP  EQU 0X55
LONG1     EQU    0X40          ;LONG1--- LONG10经度的10位数据
LONG2     EQU    0X41
LONG3     EQU    0X42
LONG4     EQU    0X43
LONG5     EQU    0X44
LONG6     EQU    0X45
LONG7     EQU    0X46
LONG8     EQU    0X47
LONG9     EQU    0X48
LONG10    EQU    0X49
T1        EQU    0X58           ;T1---T6时间的6位数据
T2        EQU    0X59
T3        EQU    0X60
T4        EQU    0X61
T5        EQU    0X62
T6        EQU    0X63
;********************************************************
       ORG  00H
       NOP
       NOP
       GOTO MAIN
       ORG  04H          ;设定按中端健才开始数据接受
       NOP
       NOP
       GOTO INTERRUPT
;*********判断头文件是不是‘$GPGGA’**********
IDMESSAGE
        BCF     STATUS,RP0
BREAK0 
     CALL      PAND
        MOVWF     TEMP1
        MOVLW     ‘$‘        ;detect $
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO   BREAK0
        CALL     PAND
        MOVWF     TEMP1
        MOVLW     ‘G‘        ;detect G
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO   BREAK0
        CALL     PAND
        MOVWF     TEMP1
        MOVLW     ‘P‘        ;detect P
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO  BREAK0
        CALL     PAND
        MOVWF     TEMP1
        MOVLW     ‘G‘        ;detect G
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO  BREAK0
        CALL     PAND
        MOVWF     TEMP1
        MOVLW     ‘G‘        ;detect G
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO  BREAK0
        CALL     PAND
        MOVWF     TEMP1
        MOVLW     ‘A‘        ;detect A
        SUBWF     TEMP1,0
        BTFSS     STATUS,Z
        GOTO  BREAK0
        CALL     PAND        ;跳过逗号
        RETURN
;************接收函数******************
RECEIVE
       CALL     PAND                    ;开始时间数据接收
       MOVWF    T1
       CALL     PAND
       MOVWF    T2
       CALL     PAND
       MOVWF    T3
       CALL     PAND
       MOVWF    T4
       CALL     PAND
       MOVWF    T5
       CALL     PAND
       MOVWF    T6                      ;时间数据接收完成
       CALL     PAND                     ;跳过逗号
       CALL     PAND                     ;跳过10位纬度数据---开始
       CALL     PAND
CALL     PAND
       CALL     PAND                    
       CALL     PAND
       CALL     PAND
       CALL     PAND                    
       CALL     PAND
       CALL     PAND
       CALL     PAND                     ;跳过10位纬度数据---结束
       CALL     PAND                     ;跳过逗号
       CALL     PAND                     ;跳过南/北纬判断位数据
       CALL     PAND                     ;跳过逗号
       CALL     PAND                     ;接受经度信号开始
       MOVWF    LONG1
       CALL     PAND
       MOVWF    LONG2
       CALL     PAND
       MOVWF    LONG3
       CALL     PAND
       MOVWF    LONG4
       CALL     PAND
       MOVWF    LONG5
       CALL     PAND
       MOVWF    LONG6
       CALL     PAND
       MOVWF    LONG7
       CALL     PAND
       MOVWF    LONG8
       CALL     PAND
       MOVWF    LONG9
       CALL     PAND
       MOVWF    LONG10                   ;接受经度信号结束
       RETURN
;***************串口寄存器中是否数据*****************
PAND  
        BCF      STATUS,RP0
CC   BTFSS PIR1,5
        GOTO CC
        MOVF     RCREG,0
        RETURN
;*****************中断函数***************************
INTERRUPT    
        BCF INTCON,7                  ;SET GIE=0屏蔽所有中端
        BCF     STATUS,RP0
        BCF     RCSTA,1               ;清除溢出错误位
        BSF       STATUS,RP0
        BCF       TXSTA,2             ;BRGH=0 Low speed
        BCF       TXSTA,4             ;Set Asynchronous mode
        MOVLW     0X0C
        MOVWF     SPBRG             ;设置波特率为4800
        BCF       STATUS,RP0
        MOVLW     B‘10010000‘
        MOVWF     RCSTA             ;串口接收相关设置
        BSF       STATUS,RP0         
        BSF       OPTION_REG,6        ; RB0/INT 引脚上升沿中断
       MOVWF W_TEMP            
    SWAPF STATUS,W
    BCF   STATUS,RP0
    MOVWF STATUS_TEMP
    BCF     STATUS,RP0
    CALL    IDMESSAGE
       CALL    RECEIVE
        BCF     STATUS,RP0
        CLRF    RCSTA                ;清除串口设置
        CALL    CONVERT             ;调用时间转换函数
OUT BCF STATUS,RP0             ;跳出中断部分,恢复寄存器
     SWAPF STATUS_TEMP,W
     MOVWF STATUS
     SWAPF W_TEMP,F
     SWAPF W_TEMP,W  
     BSF  INTCON,7     ;SET GIE=1允许所有中端
     NOP 
        RETFIE
;************ 格林威治时间转换为北京时间******************
CONVERT
       MOVLW  A‘0‘
       SUBWF  T2,1
       SUBWF  T1,1
       MOVLW  D‘10‘
       MOVWF  TEMP1
LOOP1  MOVF   TEMP1,0
       MOVF   TEMP1,1
       BTFSS  STATUS,Z
       GOTO   ADD10
       MOVLW  D‘8‘
       ADDWF  T2,1
       MOVLW  D‘24‘
       SUBWF  T2,1
       BTFSC  STATUS,C
       GOTO   CON1
       ADDWF  T2,1
       GOTO   CON1
CON1   MOVLW  D‘20‘
       MOVWF  TEMP1
       SUBWF  T2,0
       BTFSS  STATUS,C
       GOTO   CON2
       MOVWF  T2
       MOVLW  0X02
       MOVWF  T1
       GOTO   HALT1
CON2   MOVLW  D‘10‘
       MOVWF  TEMP1
       SUBWF  T2,0
       BTFSS  STATUS,C
       GOTO   CON3
       MOVWF  T2
       MOVLW  0X01
       MOVWF  T1
       GOTO   HALT1
CON3   MOVLW  0X00
       MOVWF  T1
HALT1  MOVLW  A‘0‘
       ADDWF  T1,1
       ADDWF  T2,1
       RETURN
ADD10  MOVF   T1,0
       ADDWF  T2,1
       DECF   TEMP1,1
       GOTO   LOOP1
       RETURN
;******************MAIN***********************
MAIN
        BCF       STATUS,RP0
        MOVLW     B‘10010000‘
        MOVWF     INTCON            ;打开中断
        LOOP NOP
     BCF     STATUS,RP0
     GOTO  LOOP
     GOTO MAIN
        END
//==============================================================================
转后记
实际GPS的原理是超级简单,买个模块,加上电,用TTL或者RS232,读就行了
但是在实际的使用中还是有很多细节要注意,比如辐射,冷启动等问题
理论到实践,到成品,到商用,实践上还是有一段路要走,每一步也不是想象中的那么容易,当然也不是那么的难。。。
2010-07-14 17:47:00 comelon 阅读数 2011
  • 串口通信和RS485-第1季第13部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第13个课程,主要讲解了串行通信UART及其扩展RS485。本课程很重要,因为串口通信是我们接触的早也简单的通信方式,是后续继续学习SPI、I2C甚至USB、网络通信等的基础,大家务必认证对待完全掌握。

    6005 人正在学习 去看看 朱有鹏

/**********************************************************************************
                  MS51单片机通用串口发送接收程序

数据包的帧格式为:第一字节为同步信号(SYNC)。
                  第二字节为地址(ADDRESS)。
      第三字节为命令(COMMAND)。
      第四字节为数据块的长度(DATA SIZE),值为后面要传输的数据的字节数(0~255),
                    如果该帧没有额外的数据,则应为0。
      第五字节到第DATA SIZE + 4 字节为传输的数据(DATA)。
      最后一字节为校验和(CHECKSUM),累加校验,值为前面所以数据的累加。
************************************************************************************/
#include <reg51.h>
#include <intrins.h>

 

//定义FSA状态常量
#define FSA_INIT      0     //初始状态
#define FSA_ADDRESS   1     //接收地址状态
#define FSA_COMMAND   2     //接收命令状态
#define FSA_DATASIZE  3     //接收数据的字节数状态
#define FSA_DATA      4     //接收数据状态
#define FSA_CHECKSUM  5     //接收校验状态

 

//定义信号分析常量
#define  SYNC      0x33     //同步信号的定义,可以根据自己的需求改成其它值
#define  YOUR_ADDR 0x43     //定义自己系统的地址,可以根据自己的需求改成其它值

 

//定义输入命令
  //根据自己的需求定义相关的命令
  //For example:
  #define CMD_RESET      0x01
  #define CMD_START     0x02
  #define CMD_DISPLAY   0x03
  #define CMD_CLEAR     0x04
  #define CMD_ACK       0xFF

 

#define  RECV_TIMEOUT  10 //定义超时时间

 

unsigned char
 recv_state = FSA_INIT,   //当前状态
 recv_timer = 0,          //时间计数
 recv_chksum,             //保存当前输入的校验值
 recv_ctr,                //接收数据缓冲区的索引
 recv_buf[35];            //保存接收数据

 

unsigned char
 trans_buf[7],           //输出数据缓冲区
 trans_ctr,              //输出数据指针
 trans_size,             //输出数据字节数
 trans_chksum;           //输出数据的校验字节

 

//定义命令是否合法的查询表
unsigned char code valid_cmd[256] = { //如果输入命令有效则为1
    0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //00 - 0F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 - 1F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20 - 2F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 - 3F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40 - 4F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50 - 5F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //60 - 6F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70 - 7F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80 - 8F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //90 - 9F
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //A0 - AF
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //B0 - BF
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //C0 - CF
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //D0 - DF
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //E0 - EF
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //F0 - FF
};

 

/*****************************************************************************************
功能:serial_int
描述:运行串口 FSA。
参数:无
返回:无
*****************************************************************************************/
void serial_int(void) interrupt 4
{
    unsigned char data c;
 if(_testbit_(TI) )   //输出中断
 {
     trans_ctr++;     //输出缓冲区指针加1
  if(trans_ctr < trans_size) //数据是否输出完毕
  {
      if(trans_ctr == (trans_size - 1) ) //输出校验字节
   {
       SBUF = trans_chksum;
   }
   else
   {
       SBUF = trans_buf[trans_ctr];  //输出当前字节
    trans_chksum += trans_buf[trans_ctr];  //更新校验字节
   }
  }
 }

 

if(_testbit_(RI) )   //接收中断
 {
     c = SBUF;
  switch(recv_state)
  {
   case FSA_INIT:
       if(c == SYNC)  //同步字节
    {
        recv_state = FSA_ADDRESS; //下一个状态
     recv_timer = RECV_TIMEOUT;
     recv_chksum = SYNC;
    }
    break;

   case FSA_ADDRESS:
       if(c == YOUR_ADDR)  //本系统的地址
    {
        recv_state = FSA_COMMAND;
     recv_timer = RECV_TIMEOUT;
     recv_chksum += c;
    }
    else     //不是本系统的地址
    {
        recv_state = FSA_INIT; //返回系统初始状态
     recv_timer = 0;
    }
    break;
  

   case FSA_COMMAND:
       if(!valid_cmd[c])  //命令无效
    {
        recv_state = FSA_INIT;  //返回系统初始状态
     recv_timer = 0;
    }
    else
    {
        recv_state = FSA_DATASIZE;
     recv_chksum += c;
     recv_buf[0] = c; //保存命令
     recv_timer = RECV_TIMEOUT;
    }
    break;

   case FSA_DATASIZE:   //字节个数
       recv_chksum += c;
    recv_buf[1] = c;
    if(c)   //是否有数据
    {
        recv_ctr = 2;
     recv_state = FSA_DATA;
    }
    else
    {
        recv_state = FSA_CHECKSUM;
    }
    recv_timer = RECV_TIMEOUT;
    break;

   case FSA_DATA:   //读取数据
       recv_chksum += c;
    recv_buf[recv_ctr] = c; //保存数据
    recv_ctr++;
    if ((recv_ctr - 2) == recv_buf[1] )  //数据接收完毕
    {
        recv_state = FSA_CHECKSUM;
    }
    recv_timer = RECV_TIMEOUT;
    break;

   case FSA_CHECKSUM:
       if (recv_chksum == c)   //校验字节核对正确
    {
        c = 1;              //用c表面是否要建立应答信号
       //根据需要加入自己的命令处理程序
             //命令处理程序也可以在其它的函数实现,节省中断时间,具体做法是在此处置为一标志位
    //在其它程序判断标志位是否执行命令处理程序
    //For example:
    //cmd_valid = 1;
        switch (recv_buf[0])
     {                   
      case CMD_RESET:
                 break;
      case CMD_START:
           break;
      case CMD_DISPLAY:
           break;
      case CMD_CLEAR:
            break;
      case CMD_ACK:
           break;
      default:
           break;
     }
    if (c)      //建立应答,可以根据自己的需要更改应答程序
    {
        trans_buf[0] = SYNC;   //信息头
        trans_buf[1] = YOUR_ADDR;
     trans_buf[2] = CMD_ACK;
     trans_buf[3] = 1;
     trans_buf[4] = recv_buf[1]; //被回应的命令
     trans_ctr = 0;              //设置缓冲区指针到第一个字节
     trans_size = 6;             //总共发送6个字节
     SBUF = SYNC;                //发送起始字节
     trans_chksum = SYNC;        //初始化校验值
    }
    }
   default:      //复位FSA
       recv_timer = 0;
    recv_state = FSA_INIT;
    break;
  }
 }
}

2016-01-25 11:51:38 baidu_33836580 阅读数 940
  • 串口通信和RS485-第1季第13部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第13个课程,主要讲解了串行通信UART及其扩展RS485。本课程很重要,因为串口通信是我们接触的早也简单的通信方式,是后续继续学习SPI、I2C甚至USB、网络通信等的基础,大家务必认证对待完全掌握。

    6005 人正在学习 去看看 朱有鹏

51单片机的串口,是个全双工的串口,发送数据的同时,还可以接收数据。

当串行发送完毕后,将在标志位 TI 置 1,同样,当收到了数据后,也会在 RI 置 1。

无论 RI 或 TI 出现了 1,只要串口中断处于开放状态,单片机都会进入串口中断处理程序。

在中断程序中,要区分出来究竟是发送引起的中断,还是接收引起的中断,然后分别进行处理。

看到过一些书籍和文章,在串口收、发数据的处理方法上,很多人都有不妥之处。

接收数据时,基本上都是使用“中断方式”,这是正确合理的。
即:每当收到一个新数据,就在中断函数中,把 RI 清零,并用一个变量,通知主函数,收到了新数据。

发送数据时,很多的程序都是使用的“查询方式”,就是执行 while(TI ==0); 这样的语句来等待发送完毕。
这时,处理不好的话,就可能带来问题。看了一些网友编写的程序,发现有如下几条容易出错:

1.有人在发送数据之前,先关闭了串口中断!等待发送完毕后,再打开串口中断。
这样,在发送数据的等待期间内,如果收到了数据,将不能进入中断函数,也就不会保存的这个新收到的数据。
这种处理方法,就会遗漏收到的数据。

2.有人在发送数据之前,并没有关闭串口中断,当 TI = 1 时,是可以进入中断程序的。
但是,却在中断函数中,将 TI 清零!
这样,在主函数中的while(TI ==0);,将永远等不到发送结束的标志。

3.还有人在中断程序中,并没有区分中断的来源,反而让发送引起的中断,执行了接收中断的程序。

对此,做而论道发表自己常用的方法:
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
这样一来,收、发两者基本一致,编写程序也很规范、易懂。
更重要的是,主函数中,不用在那儿死等发送完毕,可以有更多的时间查看其它的标志。
===========================================
下面看一个网上的题目,以及做而论道的解答。

求一个单片机串口通信程序  悬赏分:50 | 解决时间:2011-9-19 22:39 |
求一个PC与单片机串口通信的程序,要求如下:
1、如果在电脑上发送以$开始的字符串,则将整个字符串原样返回(字符串长度不是固定的)。
2、如果接收到1,则将P10置高电平,接收到0,P10置低电平。(用来控制一个LED)

单片机是STC89C52RC/晶振11.0592/波特率要求是9600或4800。谢谢!

问题补充:可能会将【$ABCD,123456,987654ccc,aasdasd,aaaa,sssd,4D】这样的字符串(字符串长度约为50-150个字符)传送给单片机,只能能原样返回。
//----------------------------------------------
最佳答案:

下列程序,已经调试成功。
#include <REG52.H>

sbit LED = P1^0;
unsigned char UART_buff;
bit New_rec = 0, Send_ed = 1, Money = 0;
//----------------------------------------------
void main (void)
{
    SCON = 0x50;   //串口方式1, 8-n-1, 允许接收.
    TMOD = 0x20;   //T1方式2
    TH1 = 0xFD;    //9600bps@11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;                       
    ES  = 1;       //开中断.
    EA  = 1;

    while(Money == 0);    //等着交费,呵呵,等着接收$.

    while(1)  {
      if ((New_rec == 1) && (Send_ed == 1))  {  //如果收到新数据及发送完毕
        SBUF = UART_buff; //那就发送.
        New_rec = 0;
        Send_ed = 0;
    } }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
    if(RI == 1) {  //如果收到.
      RI = 0;      //清除标志.
      New_rec = 1;
      UART_buff = SBUF;  //接收.
      if(UART_buff == '1')  LED = 1;
      if(UART_buff == '0')  LED = 0;
      if(UART_buff == '$')  Money = 1;
    }
    else  {        //如果送毕.
      TI = 0;      //清除标志.
      Send_ed = 1;
    }
}
//----------------------------------------------
回答时间:2011-9-19 14:19 |
回答者: 做而论道 | 十五级采纳率:42%
提问者对于答案的评价:测试通过。感谢。
原题网址:http://zhidao.baidu.com/question/320858150.html
后记:该题目的几个答案,都不正确,丢失数据的现象比较严重,大家可以自己测试一下。
//----------------------------------------------

2017-08-11 08:40:46 yueqiuchen 阅读数 1127
  • 串口通信和RS485-第1季第13部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第13个课程,主要讲解了串行通信UART及其扩展RS485。本课程很重要,因为串口通信是我们接触的早也简单的通信方式,是后续继续学习SPI、I2C甚至USB、网络通信等的基础,大家务必认证对待完全掌握。

    6005 人正在学习 去看看 朱有鹏

最近有个小的训练

大致是需要用摄像头检测圆,然后把圆的xy坐标发送给单片机。

但是网上大部分都是基于MFC串口控件的例程。大海捞针找到了个win32命令控制台的串口例程 ,自己改了一下贡献出来。

 

直接调用API实现串口通信

 

两个例程

如果编译运行有问题 直接复制源文件到新win32命令工程中运行


平台-VS2013-win32


例程1:摄像头识别小圆,然后通过串口输出小圆的xy坐标。单片机可以直接接受,具体串口配置自己配置。摄像头需要 opencv的库,我的库是opencv2.4.12。

 

例程2:VSwin32命令控制台程序 调用串口,可以根据自己需要配置串口,完成windows与单片机的数据传输。可作为开发参考使用。

 

代码写的很烂,玩一玩还行,仅供参考。

 

最新1C币下载链接:https://download.csdn.net/download/yueqiuchen/10452176

51单片机串口程序

阅读数 2962

单片机串口通信

阅读数 232

没有更多推荐了,返回首页