D3 - 嵌入式C的高级用法

下面是自我测试

  • | 讲述GCC编译流程与编译指令和生成的文件后缀是什么,是什么类型?
  • | .c文件什么gcc指令成为.i文件; .c文件什么gcc指令成为.s文件;.c文件什么gcc指令成为.o文件
  • | 如何进入gdb调试,如何使用gdb查看文件,设置断点,如何设置断点,如何查看变量值,如何单步运行,如何查看断点情况
  • | main函数的标准格式是什么,第一个参数是什么意思,第二个参数是什么意思,Linux命令就是这么实现的
  • | 什么函数控制led灯,蜂鸣器这些io
  • | 什么是串口,什么是流控
  • | 读取串口当前参数的函数是什么;提取输入波特率函数是什么;提取输入波特率函数是什么;输入输出波特率设置函数是什么;清空串口缓存的函数的声明;设置串口参数的函数是声明
  • | 串口的接收与发送函数是什么

下面是知识介绍

提问:讲述GCC编译流程与编译指令和生成的文件后缀是什么,是什么类型?在这里插入图片描述
GCC编译流程,i是input,所以预编译是i,o是out,所以汇编后是o;gcc就是把用户的c文件弄成二进制文件o,这些二进制文件就是字节码文件就是机器文件,机器通过识别101010来对应不同的架构内的指令进行执行(由于我们一般不叫做二进制文件,不好听,叫做目标文件,再链接其他二进制文件,组成最后的二进制文件exe在这里插入图片描述
GCC支持的后缀在这里插入图片描述
分析器将源代码转换为汇编语言
汇编器将汇编语言转换为CPU可执行的字节码
链接器将汇编器生成的单独的目标文件组合成可执行的应用程序
GCC命令参数1:-c,只对开c文件解析,最后生成二进制目标.o文件;-E就是只生成.i文件(E等于1的意思,就是只进行一步,也就是预编译;-S就是生成.s文件,s对s这个好记
在这里插入图片描述
2:-g 用于源代码调试代码
3:-O,优化编译;产生的可执行文件的执行效率提高,但是编译、连接的速度就相应地要慢一些。
4:-O2,比-O更好的优化效果,编译速度也更慢
6:-L 链接库
7:-E生成预处理代码
在这里插入图片描述
8:-S生成汇编代码
在这里插入图片描述
10:gcc 生成可执行文件
GDB调试工具示例:
在这里插入图片描述
GDB命令在这里插入图片描述
l
look查看代码
在这里插入图片描述
b
设置断点
在这里插入图片描述
del
删除断点
删除第一第二个断点
在这里插入图片描述
info b
查看断点情况
在这里插入图片描述
r
运行代码
在这里插入图片描述
printf
查看变量值
在这里插入图片描述
n
单步运行
在这里插入图片描述
c
退出调试,恢复程序运行
在这里插入图片描述
q
退出调试
在这里插入图片描述
help
帮助
main函数的参数int main(int argc,char **argv)
argc = 参数的个数
**argv=存储输入字符的数组
在这里插入图片描述
结果验证:
在这里插入图片描述
为什么要对main函数进行传参,项目模块开发的时候,测试main函数功能就使用这种方式,在Linux很常见
字符设备控制LED灯要会使用ioctl函数;注意open打开的文件是开发板dev下的leds,将用arm编译器编译好的可执行文件拷贝到TF卡中,再将TF卡挂载到开发板进行执行(如果运行时打印U盘文件系统只读,将U盘重新格式化一次即可)
在这里插入图片描述
验证开发板,观察到开发板的不同IO输出不同电平,对应控制两个灯开关
在这里插入图片描述
字符设备控制之蜂鸣器操作过程与代码和LED灯的完全一致
在这里插入图片描述
串口编程的知识点串口就是串行的接口,就是一个一个bite的接收与发送的通道,RS232就是串口;打个比方,接收到0x1111后面的数据才是真正的数据,这个过程就是流控,就是确定哪些数据有效的

(1)打开开发板串口;由于操作系统能自动识别硬件并编号,所以打开串口和打开文件一样方便
在这里插入图片描述

(2)串口初始化过程:先读取当前参数,修改参数,配置参数
(2.1)读取串口当前参数函数是tcgetattr(attr=attribute=属性;tc=translate control)
在这里插入图片描述

(2.2)提取输入波特率函数;cf=控制频率,cfgetispeed=控制频率之获取输入速度
在这里插入图片描述

(2.3)提取输出波特率函数
在这里插入图片描述

(2.4)输入与输出波特率的设置函数
在这里插入图片描述

(2.5)清空串口buffer中的数据的函数
在这里插入图片描述

(2.6)设置串口参数的函数
在这里插入图片描述

(3)串口发送与接收与对文件操作一样使用write和read函数;向串口驱动文件写入数据就是串口向外发送数据;向串口驱动文件接收数据就是串口接收发来的数据
开发板串口发送数据的编程实例
===============================================================================

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>

int set_opt(int,int,int,char,int);//函数声明的格式,可以先不用写参数名
void main()
{
	int fd,wr_static,i=10;
	char *uart3 = "/dev/ttySAC3"; //识别的设备驱动文件
	char *buffer = "hello world!\n";
	
	printf("\r\nitop4412 uart3 writetest start\r\n");

	//打开串口文件
	if((fd = open(uart3, O_RDWR|O_NOCTTY|O_NDELAY))<0){
		printf("open %s is failed",uart3);
	}
	else{
		printf("open %s is success\n",uart3);

		//设置串口参数
		set_opt(fd, 115200, 8, 'N', 1); 

		//发送10次
		while(i--)
		{
			//向串口文件写入数据,串口再向外发送数据
			wr_static = write(fd,buffer, strlen(buffer));
			if(wr_static<0)
				printf("write failed\n");
			else{
				printf("wr_static is %d\n",wr_static);
			}
			sleep(1);
		}
	}
	close(fd);//最后记得关闭文件描述符
}


int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{

	struct termios newtio,oldtio;//串口结构体句柄

	//获取串口参数信息,存放在okldtio结构体
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}

	//清空结构体
	bzero( &newtio, sizeof( newtio ) );

	
	//c_iflag;	  /* input modes */
	//c_oflag;	  /* output modes */
	//c_cflag;	  /* control modes */
	//c_lflag;	  /* local modes */
	//c_cc[NCCS];   /* special characters */

	newtio.c_cflag  |=  CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;

	switch( nBits )
	{
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 8:
		newtio.c_cflag |= CS8;
		break;
	}
	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}



	switch( nSpeed )
	{
	case 2400:
		cfsetispeed(&newtio, B2400); //设置输入波特率
		cfsetospeed(&newtio, B2400); //设置输出波特率
		break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
		break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
		break;
	case 460800:
		cfsetispeed(&newtio, B460800);
		cfsetospeed(&newtio, B460800);
		break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	}
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
	newtio.c_cflag |=  CSTOPB;
	newtio.c_cc[VTIME]  = 0;
	newtio.c_cc[VMIN] = 0;
	tcflush(fd,TCIFLUSH);  //清空串口缓冲区

	//将串口结构体参数写入硬件;前面的都是写入结构体
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	return 0;
}

/* 下面是c_cflag参数的可选值
c_cflag flag constants:

CBAUD  (not in POSIX) Baud speed mask (4+1 bits).  [requires _BSD_SOURCE or _SVID_SOURCE]

CBAUDEX
	   (not in POSIX) Extra baud speed	mask  (1  bit),  included  in  CBAUD.	[requires
	   _BSD_SOURCE or _SVID_SOURCE]

	   (POSIX  says that the baud speed is stored in the termios structure without speci‐
	   fying where precisely, and provides cfgetispeed() and cfsetispeed() for getting at
	   it.	 Some  systems use bits selected by CBAUD in c_cflag, other systems use sepa‐
	   rate fields, for example, sg_ispeed and sg_ospeed.)

CSIZE  Character size mask.  Values are CS5, CS6, CS7, or CS8.

CSTOPB Set two stop bits, rather than one.

CREAD  Enable receiver.

PARENB Enable parity generation on output and parity checking for input.

PARODD If set, then parity for input and output is odd; otherwise even parity is used.

HUPCL  Lower modem control lines after last process closes the device (hang up).

CLOCAL Ignore modem control lines.

LOBLK  (not in POSIX) Block output from a noncurrent shell layer.  For use by shl  (shell
	   layers).  (Not implemented on Linux.)

CIBAUD (not in POSIX) Mask for input speeds.  The values for the CIBAUD bits are the same
	   as  the	values	for  the  CBAUD  bits,	shifted  left  IBSHIFT	bits.	[requires
	   _BSD_SOURCE or _SVID_SOURCE] (Not implemented on Linux.)

CMSPAR (not  in  POSIX)  Use  "stick"  (mark/space)  parity  (supported on certain serial
	   devices): if PARODD is set, the parity bit is always 1; if PARODD is not set, then
	   the parity bit is always 0).  [requires _BSD_SOURCE or _SVID_SOURCE]

CRTSCTS
	   (not  in  POSIX) Enable RTS/CTS (hardware) flow control.  [requires _BSD_SOURCE or
	   _SVID_SOURCE]

*/
/* 下面是c_iflag的可选值
c_iflag flag constants:

       IGNBRK Ignore BREAK condition on input.

       BRKINT If IGNBRK is set, a BREAK is ignored.  If it is not set but BRKINT is set, then  a
              BREAK causes the input and output queues to be flushed, and if the terminal is the
              controlling terminal of a foreground process group, it will cause a SIGINT  to  be
              sent  to this foreground process group.  When neither IGNBRK nor BRKINT are set, a
              BREAK reads as a null byte ('\0'), except when PARMRK is set,  in  which  case  it
              reads as the sequence \377 \0 \0.

       IGNPAR Ignore framing errors and parity errors.

       PARMRK If IGNPAR is not set, prefix a character with a parity error or framing error with
              \377 \0.  If neither IGNPAR nor PARMRK is set, read  a  character  with  a  parity
              error or framing error as \0.

       INPCK  Enable input parity checking.

       ISTRIP Strip off eighth bit.

       INLCR  Translate NL to CR on input.

       IGNCR  Ignore carriage return on input.

       ICRNL  Translate carriage return to newline on input (unless IGNCR is set).

       IUCLC  (not in POSIX) Map uppercase characters to lowercase on input.

       IXON   Enable XON/XOFF flow control on output.

       IXANY  (XSI)  Typing any character will restart stopped output.  (The default is to allow
              just the START character to restart output.)

       IXOFF  Enable XON/XOFF flow control on input.

       IMAXBEL
              (not in POSIX) Ring bell when input queue is full.  Linux does not implement  this
              bit, and acts as if it is always set.

       IUTF8 (since Linux 2.6.4)
              (not  in  POSIX)  Input  is UTF8; this allows character-erase to be correctly per‐
              formed in cooked mode.
*/

/*下面是c_clag参数的可选值

c_cflag flag constants:

	  CBAUD  (not in POSIX) Baud speed mask (4+1 bits).  [requires _BSD_SOURCE or _SVID_SOURCE]

	  CBAUDEX
			 (not in POSIX) Extra baud speed  mask	(1	bit),  included  in  CBAUD.   [requires
			 _BSD_SOURCE or _SVID_SOURCE]

			 (POSIX  says that the baud speed is stored in the termios structure without speci‐
			 fying where precisely, and provides cfgetispeed() and cfsetispeed() for getting at
			 it.   Some  systems use bits selected by CBAUD in c_cflag, other systems use sepa‐
			 rate fields, for example, sg_ispeed and sg_ospeed.)

	  CSIZE  Character size mask.  Values are CS5, CS6, CS7, or CS8.

	  CSTOPB Set two stop bits, rather than one.

	  CREAD  Enable receiver.

	  PARENB Enable parity generation on output and parity checking for input.

	  PARODD If set, then parity for input and output is odd; otherwise even parity is used.

	  HUPCL  Lower modem control lines after last process closes the device (hang up).

	  CLOCAL Ignore modem control lines.

	  LOBLK  (not in POSIX) Block output from a noncurrent shell layer.  For use by shl  (shell
			 layers).  (Not implemented on Linux.)

	  CIBAUD (not in POSIX) Mask for input speeds.	The values for the CIBAUD bits are the same
			 as  the  values  for  the	CBAUD  bits,  shifted  left  IBSHIFT  bits.   [requires
			 _BSD_SOURCE or _SVID_SOURCE] (Not implemented on Linux.)

	  CMSPAR (not  in  POSIX)  Use	"stick"  (mark/space)  parity  (supported on certain serial
			 devices): if PARODD is set, the parity bit is always 1; if PARODD is not set, then
			 the parity bit is always 0).  [requires _BSD_SOURCE or _SVID_SOURCE]

	  CRTSCTS
			 (not  in  POSIX) Enable RTS/CTS (hardware) flow control.  [requires _BSD_SOURCE or
			 _SVID_SOURCE]
*/

==============================================================================================

串口接收例程
=======================================================================================
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>

int set_opt(int,int,int,char,int);
//"/dev/ttySAC3"是con2,靠近耳机接口的串口
void main()
{
	int fd,nByte;
	char *uart3 = "/dev/ttySAC3";
	char buffer[512];
	char *uart_out = "please input\r\n";

	//清空接收缓存
	memset(buffer, 0, sizeof(buffer));

	//打开串口
	if((fd = open(uart3, O_RDWR|O_NOCTTY))<0)
		printf("open %s is failed",uart3);
	else{
		//设置串口参数
		set_opt(fd, 115200, 8, 'N', 1);
		write(fd,uart_out, strlen(uart_out));
		while(1){

			//读取usart驱动文件的数据 == usart接收数据
			while((nByte = read(fd, buffer, 512))>0){
				buffer[nByte+1] = '\0';			
				write(fd,buffer,strlen(buffer));
				memset(buffer, 0, strlen(buffer));
				nByte = 0;
			}
		}
	}
}

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;

	switch( nBits )
	{
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
	}

	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}

	switch( nSpeed )
	{
		case 2400:
			cfsetispeed(&newtio, B2400);
			cfsetospeed(&newtio, B2400);
			break;
		case 4800:
			cfsetispeed(&newtio, B4800);
			cfsetospeed(&newtio, B4800);
			break;
		case 9600:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
	}
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;
		newtio.c_cc[VTIME]  = 0;
		newtio.c_cc[VMIN] = 0;
		tcflush(fd,TCIFLUSH);
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	
	//	printf("set done!\n\r");
	return 0;
}

=======================================================================================


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值