单片机与arm串口通信

1.单片机STC89C52 程序如下

#include<reg52.h>
#include<intrins.h>
 
#define uchar unsigned char
#define uint  unsigned int 
 
/********************************************************************
* 名称 : Com_Init()
* 功能 : 初始化串口程序,晶振11.0592, 波特率9600
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Init(void)
{
  /* SCON=0x50;   
   TH2=0xFF;           
   TL2=0xFD;   
   RCAP2H=0xFF;   
   RCAP2L=0xFD; 


   TCLK=1;   
   RCLK=1;   
   C_T2=0;   
   EXEN2=0;


   TR2=1 ;
   TI = 1;*/
    TMOD = 0x20;
     PCON = 0x00;
     SCON = 0x50;            
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;    
            
}
 
void delay_ms(unsigned int n)            //延时10×n毫秒程序
{
    unsigned int i,j;
    for(i=0;i<n;i++)
        for(j=0;j<2000;j++);
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
    char i = 0;
    char code Buffer[] = "abcdef 123456 ABCDEF";
    char *p;
    Com_Init();
    //P2 = 0x00;
    while(1)
    {
        p = Buffer;
        while(1)
        {
            SBUF = *p;
            while(!TI)                       //如果发送完毕,硬件会置位TI = 1
            {
                _nop_();        //延时一个指令周期
            }
            p++;
            if(*p == '\0')
             break;                //在每个字符串的最后,会有一个'\0'
            TI = 0;                        //TI清零
        }
        TI = 0;                            //TI清零
        delay_ms(100);
    }
}

2.Linux程序如下

#include     <stdio.h>
#include     <stdlib.h> 
#include     <unistd.h>  
#include     <sys/types.h>
#include     <sys/stat.h>
#include     <fcntl.h> 
#include     <termios.h>
#include     <errno.h>
#include     <string.h>
 
#define SERIAL_PORT            "/dev/ttyUSB0"    //串口地址
#define PORT_SPEED        9600        //串口波特率
#define    DATABITS            8        //数据位
#define STOPBITS            1        //停止位
#define    PARITY                'n'        //校验方式 (不校验)
 
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300,B115200};
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300, 38400,  19200,  9600, 4800, 2400, 1200,  300,115200};
 
int setSpeed(int, int, struct termios);
int setParity(int, int, int, int, struct termios);        
int openPort(void);
int init(void);
void readPort(int);
 
int main()
{
    char *quit = (char*)malloc(sizeof(char*));
    int fd;
       
 
  char write_buf[256];
 
    fd = init();//初始化端口设置
    
    printf("configure complete\n"); 
    printf("start send and receive data...\n");
  
  while(1)
  {        
      readPort(fd);
    }
    close(fd);
}
 
void readPort(int fd)
{
      int i;
      int len;
      int n; 
      char read_buf[256];
      while(1)
      {
            bzero(read_buf, sizeof(read_buf));    
         
            while((n = read(fd, read_buf, sizeof(read_buf))) > 0)
          {
                printf("Len %d \n", n);
                read_buf[n + 1] = '\0';
                  printf("[%s]\n", read_buf);
          }
      }
}
/************************************
 *init 
 *    初始化串口
 *@global
 *    PORT_SPEED    串口波特率
 *    DATABITS    数据位
 *    STOPBITS    停止位
 *    PARITY        校验方式
 *@return
 *    -1:设置失败  !(-1):设置成功
 ************************************/
int init(void)
{
    int fd;
    struct termios opt;    //定义termios结构
 /*
  这个变量被用来提供一个健全的线路设置集合, 如果这个端口在被用户初始化前
  使用. 驱动初始化这个变量使用一个标准的数值集               
  struct termios{
      unsigned short c_iflag; //输入模式标志
    unsigned short c_oflag;     //输出模式标志
    unsigned short c_cflag;     //控制模式标志
    unsigned short c_lflag;     //区域模式标志或本地模式标志或局部模式
    unsigned char c_line;     //行控制line discipline 
    unsigned char c_cc[NCC];     // 控制字符特性
  };
    */
  //打开串口
  fd = openPort();
  
  //设置波特率
  if(setSpeed(fd, PORT_SPEED, opt) == 1)
  {    
      printf("setSpeed failed!\n");
      exit(1);
  }
  
  //设置数据位、停止位和校验位
  if(setParity(fd, DATABITS, STOPBITS, PARITY, opt) == 1)
  {
      printf("setParity failed!\n");
      exit(1);
  } 
  if(tcsetattr(fd, TCSANOW, &opt) != 0)    //TCSANOW:不等数据传输完毕就立即改变属性。
    {                //TCSADRAIN:等待所有数据传输结束才改变属性。
      perror("serial error");
      return -1;
  }
  return fd;
}
/************************************
 *openPort  
 *    打开串口
 *@global
 *    SERIAL_PORT    串口地址
 *@return
 *    -1:设置失败  !(-1):设置成功
 ************************************/
int openPort()
{
    int fd;
    //O_RDWR:    可读写方式打开;
    //O_NOCTTY:    若打开的文件为终端机设备时则不会把该终端机当做进程控制终端机
    //O_NDELAY:    以不可阻断的方式打开文件
    fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY |O_NDELAY);   
      if(fd == -1)
      {
        perror("open serial failed!\n");
          exit(1);
      }    
      return fd;
}
 
/************************************
 *setSpeed  
 *    设置波特率(38400, 19200, 9600, 4800, 2400, 1200, 300)
 *@para
 *    fd                文件标识。
 *    speed                波特率。
 *  struct termios            termios结构变量
 *@return
 *    1:设置失败  0:设置成功
 ************************************/
int setSpeed(int fd, int speed, struct termios Opt)
{
    int i;
 
    //if(tcgetattr(fd, &Opt) != 0) //获取与终端相关的参数;    #并将获得信息保存在 opt 变量中
    if(tcgetattr(STDIN_FILENO, &Opt) != 0)
    {
        perror("tcgetattr fd\n");
        return 1;
    }
    //识别波特率,设置输入输出波特率
    for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
        if(speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            //设置波特率
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            
            //设置数据接收方式
            if(tcsetattr(fd, TCSANOW, &Opt) != 0)
            {
                perror("tcsetattr fd");
                return 1;
            } 
            tcflush(fd, TCIOFLUSH);
        }
    }
    return 0;
}
 
/************************************
 *setParity 
 *    设置数据位、停止位和校验位
 *@para
 *    fd                文件标识。
 *    databits            数据位。(8 | 7)
 *    stopbits            停止位。(1 | 2)
 *    parity                校验位。(n:无校验位 | o:奇校验 | e:偶校验 | s:空格)
 *@return
 *    1:设置失败  0:设置成功
 ************************************/
int setParity(int fd, int databits, int stopbits, int parity, struct termios Opt)
{
    if(tcgetattr(fd, &Opt) != 0)
    {
        perror("tcgetattr fd");
        return 1;
    }
        Opt.c_cflag |= (CLOCAL | CREAD);           //CLOCAL:忽略 modem 控制线。 
                            //CREAD:    打开接受者。
    switch(databits)                       //设置数据位数
    {
        case 7:
            Opt.c_cflag &= ~CSIZE;            //屏蔽字符大小位
            Opt.c_cflag |= CS7;            //选择7位数据位
            break;
        case 8:
            Opt.c_cflag &= ~CSIZE;
            Opt.c_cflag |= CS8;
            break;
        default:
            fprintf(stderr, "Unsupported data size.\n");
            return 1;
    }
 
    switch(parity)            //设置校验位
    {
    case 'n':
        Opt.c_cflag &= ~PARENB;                    //清除校验位
        Opt.c_iflag &= ~INPCK;                    //启用输入奇偶检测。  
        break;
    case 'o':
        Opt.c_cflag |= PARENB;                   //使能校验位
        Opt.c_cflag |= PARODD;                    //奇校验
        Opt.c_iflag |= INPCK;                    //启用输入奇偶检测。
        break;
    case 'e':
        Opt.c_cflag |= PARENB;                   //使能校验位
        Opt.c_cflag &= ~PARODD;                    //偶校验
        Opt.c_iflag |= INPCK;                    //启用输入奇偶检测。
        break;
    case 's':
        Opt.c_cflag &= ~PARENB;                    //清除校验位
        Opt.c_cflag &= ~CSTOPB;                   //设置一个停止位
        Opt.c_iflag |= INPCK;                    //启用输入奇偶检测。
        break;
    default:
        fprintf(stderr, "Unsupported parity.\n");
        return 1;    
    }
 
    switch(stopbits)        //设置停止位
    {
    case 1:
        Opt.c_cflag &= ~CSTOPB;
        break;
    case 2:
        Opt.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr, "Unsupported stopbits.\n");
        return 1;
    }
 
    Opt.c_cflag |= (CLOCAL | CREAD);
 
    Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    
 
    Opt.c_oflag &= ~OPOST;        //OPOST :启用具体实现自行定义的输出处理。
    Opt.c_oflag &= ~(ONLCR | OCRNL);    //OCRNL :将输出中的回车映射为新行符  
                         //ONLCR :(XSI) 将输出中的新行符映射为回车-换行。
    
    Opt.c_iflag &= ~(ICRNL | INLCR);        //ICRNL :将输入中的回车翻译为新行 (除非设置了 IGNCR)(否则当输入信号有 CR 时不会终止输入)。 
                            //INLCR :将输入中的 NL 翻译为 CR。(将收到的换行符号转换为Return)
    Opt.c_iflag &= ~(IXON | IXOFF | IXANY);    //IXON     :启用输出的 XON/XOFF 流控制。
                            //IXOFF :启用输入的 XON/XOFF 流控制。
                        //IXANY :(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出。
    tcflush(fd, TCIFLUSH);            //清空输入缓存
    
    //MIN = 0 , TIME =0; 有READ立即回传否则传回 0,不读取任何字元
    Opt.c_cc[VTIME] = 0;                    
    Opt.c_cc[VMIN] = 0;                            
    
    if(tcsetattr(fd, TCSANOW, &Opt) != 0)    //设置数据接收方式
    {
        perror("tcsetattr fd");
        return 1;
    }
 
    return 0;
}
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值