单片机和虚拟机里的Linux进行串口通信

最近在做单片机的火焰传感器采集数据并且并且将危险信息发送给PC端的Linux。一直卡在Linux端的,所以,做了各种尝试,参考了网上一篇大神的代码,终于把自己的东西弄了出来。

先说明设备吧,CC2530单片机、linux下的pl2303的驱动、虚拟机环境下的CentOS以及minicom。

下面我把单片机端的代码贴出来:

/*
 ************************************************
 *Name : serial_communication_CC2530            *
 *Date : 2015-04-29                             *
 *Author : Sniper                               *
 *Aim : fire sensor check the fire and send the *
 *      message to linux wihich though the      *
 *      serial port.                            *
 ************************************************
 */
#include "ioCC2530.h"
#include <string.h>
#include <stdlib.h>

#define uchar unsigned char
#define uint unsigned int
void Uart_send_char(int data);

uchar Recdata[]="fire!";

/*
 * init the clock
 */
void initclk(void)
{
  SLEEPCMD&= ~0X04;
  CLKCONCMD = 0X10;
  while(CLKCONSTA!=0X10);
  SLEEPCMD = 0X04;		//主频32M  	
}

/*
 *init the uart
 */
void inituart(void)
{
  IEN0|=0x84;//总中断,接收中断使能
  U0CSR|=0xc0;//UART模式,允许接收
  
  U0GCR=10;
  U0BAUD=59;
}
 
/*
 *init the IO
 */
void initio(void)
{
 P0SEL|=0x0c; 
}

/*
 *Uart send the string
 */
void UartTX_Send_String(uchar Data[],int len)
{
  int j;
  for(j=0;j<len;j++)
  {
    U0DBUF = *Data++;
    while(UTX0IF == 0);
    UTX0IF = 0;
  }
}

/*
 *fire sensor check the fire , if the fire is occured.
 *It will send the message.
 */
int main(void)
{	
  initio();
  initclk();
  inituart();
  
  P0DIR|=0x40;
  int i=0;
  
  while(1)
  {   
    if((P0&0x20)&& (i==0))
    {
      UartTX_Send_String(Recdata,sizeof(Recdata));
      i++;
    }
    else if(!(P0&0x20))
    {
      i=0;
    }
  }
}

/*
 *interupt
 */
#pragma vector=URX0_VECTOR
__interrupt void UART0_IRQ(void)
{
  URX0IF=0;
  U0DBUF=U0DBUF;
  while(!UTX0IF);
  UTX0IF=0;
}
这个是linux端的代码,因为我用的设备设置是波特率38400、串口ttyUSB0、数据位8位、停止位1位、无校验方式。

/*
 *************************************************
 *Name : Serial_communication.c            * 
 *Date : 2015-04-29                        *
 *Author : Sniper                          *
 *Aim : make the CC2530 single chip and    *
 *      Linux (CentOS) communication.      *
 *      Linux receive and print the message*
 *************************************************
 */
#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>  
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
/*
 *terminal device header file
 */
#include <termios.h>	
#include <errno.h>
#include <string.h>


/*
 *struct 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]; 	// 控制字符特性
	};
 */
 

#define	SERIAL_PORT		"/dev/ttyUSB0"	//串口地址
#define	PORT_SPEED			38400	//串口波特率
#define	DATABITS			8		//数据位
#define	STOPBITS			1		//停止位
#define	PARITY				'n'		//校验方式 (不校验)


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];
	
	memset(write_buf,'\0',sizeof(write_buf));
	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];
	
	memset(read_buf,'\0',sizeof(read_buf));
	while(1)
	{
		bzero(read_buf, sizeof(read_buf)); 

		while((n = read(fd, read_buf, sizeof(read_buf))) > 0)
		{
			printf("%s\n", read_buf);
		}
	}
}

/*
 *init serial port
 *1 failure, 0 success
 */
int init(void)
{
	int fd;
	struct termios opt;	//定义termios结构
	//打开串口
	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  function
 *1 failure, 0 success
 */
int openPort()
{
	int fd;

	/*
	 *serial address is /dev/ttyUSB*, open the serial address
	 */
	fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY |O_NDELAY);   
  	if(fd == -1)
  	{
		perror("open serial failed!\n");
  		exit(1);
  	}    
  	return fd;
}

/*
 *setSpeed  
 *	SetSpeed(38400, 19200, 9600, 4800, 2400, 1200, 300)
 *  1 failure, 0 success
 */
int setSpeed(int fd, int speed, struct termios *Opt)
{
    int i;

    if(tcgetattr(STDIN_FILENO, &Opt) != 0)
    {
        perror("tcgetattr fd\n");
        return 1;
    }
    
    /*
     *set speed
     */
	tcflush(fd, TCIOFLUSH);
	cfsetispeed(&Opt, speed);
	cfsetospeed(&Opt, speed);

	//set ways of receive 
	if(tcsetattr(fd, TCSANOW, &Opt) != 0)
	{
		perror("tcsetattr fd");
		return 1;
	}
	tcflush(fd, TCIOFLUSH);
  
    return 0;
}

/*
 *setParity 
 *set the data bit,stop bit and check bit
 *	 1 failure, 0 success
 */
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);       	
	
	/*
	 *Data bit
	 */
	Opt.c_cflag &= ~CSIZE;
	Opt.c_cflag |= CS8;
		
	/*
	 *check bit 
	 */			
	Opt.c_cflag &= ~PARENB;        			
	Opt.c_iflag &= ~INPCK;        			  
			
	/*
	 *stop bit
	 */
	Opt.c_cflag &= ~CSTOPB;
			

	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;
}

运行方式:(1)生成可执行文件,执行。(2)打开minicom,设置相关参数。(3)接上单片机,并且打开电源。

linux端的代码参考了一下网址,此外,因为个人需要,做了相应的缩减,望大家批评指正:

http://blog.csdn.net/cooljun008/article/details/8181906

这个单片机可以使用别的单片机,只要通信的方式的参数对了,应该都可以通信。

下面一篇会分享两者通过串口双向通信,敬请期待!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值