每天一个小知识

模块化编程

1、函数的声明定义写在头文件中,具体实现写在另一个.c

2、main函数想使用哪个模块函数就只需要将头文件引入主程序.c中

3、最后链接的时候会结合在一起

3.8  环境变量

环境变量与文件路径绑定,在linux中可以使用环境变量名代替文件路径

输入env 显示所有环境变量  环境变量=文件路径名(除了代替文件路径还可以代替其他的)

输入 echo $环境变量名   ,查看环境变量的值

系统环境变量:公共的,对全部的用户都生效。

用户环境变量:用户私有的、自定义的个性化设置,只对该用户生效

系统环境变量文件是/etc/profile,用户环境变量文件是etc/.bashrc,一般推荐修改etc/.bashrc

在shell中输入修改环境变量     export ORACLE_HOME=/oracle/home    关掉终端就失效了

3.9 gcc编译

gcc是一个多语言的编译器套件,以gc编译器为核心的编译工具

后面的 -o 是给新文件起一个名字叫做hello.i ,下面是一个预处理后的代码中的一部分

只有编译部分是gcc工作,其他时候都是gcc调用其他的东西执行的

最简单的编译命令,会生成一个a.out的可执行文件

链接器

我们代码不是在一个除了一个.c文件之外,还存在其他.c文件,编译是以.c为单位进行。

当我们某个代码要调用另一个.c文件中的代码的时候,这就需要我们链接器起作用,可以帮我们找到我们需要调用的

库文件

一般就是将一个函数搞进库文件里面,然后我们调用这个库文件就可以直接使用这个函数

一种可以执行、复用代码的二进制形式(本身不可以执行,但是可以被操作系统载入内存中执行)

静态库

简单看成是一组目标文件.o的集合,即很多目标文件经过压缩打包形成的一个文件

链接器从静态库中取得所需的代码就可以,复制到生成可执行文件

动态库

3.9交叉编译工具链的安装

1、将工具链代码移动到/usr/local/arm,然后解压

2、将工具链路径加入/etc/profile,打开/etc/profile  输入export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin

arm-linux-gnueabihf-gcc -v查看版本

arm-linux-gnueabihf  就是编译链执行的应用程序集合,下面是全部的子程序

3.9 Makefile

 main: main.o input.o calcu.o
      gcc -o main main.o input.o calcu.o
 main.o: main.c
     gcc -c main.c
 input.o: input.c
      gcc -c input.c
 calcu.o: calcu.c
      gcc -c calcu.c
  
 clean:
     rm *.o
     rm main

注意空出来的是使用TAB,不要使用空格。

使用make 就会在当前目标查找Makefile文件,然后运行

main(目标):main.o(依赖) input.o(依赖) calcu.o(依赖)

当依赖不足的时候,就会向下运行查找

使用make clean 就会运行clean:下面的两条指令

变量

$符号表示取变量的值,当变量名多于一个字符时,使用"( )"
$符的其他用法

$^ 表示所有的依赖文件
$@ 表示生成的目标文件
$< 代表第一个依赖文件

注意:所有的自动变量只能出现在命令的位置,不能出现在依赖项和目标中

一个规则

(1)目标的时间必须晚于依赖项的时间,否则目标跟踪

(2)依赖项不存在,找新的规则看有没有产生依赖性的

makefile中第一个对象目标是终极目标,所有要将最终生成的.out放在makefile开头命令

也可以强制指定终极目标ALL关键字

ALL:a.out

两个函数

src = $(wildcard *.c)找到当前目录下所有后缀为.c的文件赋值给src

obj = $(patsubst %.c,%.o,$(src)将src变量中的所有后缀为.c的替换成.o

 伪目标.PHONY

伪目标只是一个标签,chean是一个伪目标没有依赖文件,只有用make来调节的时候才会执行

使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出
现名字冲突,有时候我们需要编写一个规则用来执行一些命令
解决办法就是使用伪目标

objects = main.o input.o calcu.o  //定义变量
main: $(objects)      //规则,用于编译main这个程序。该规则依赖于前面定义的objects变量中的文件
    gcc -o main $(objects)

.PHONY : clean  //声明一个伪目标

%.o : %.c      //规则
     gcc -c $<   //命令,# 使用gcc编译器编译$<(即第一个依赖项,即.c文件)为.o文件 

 clean:
     rm *.o
    rm main

上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当
我们输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行。可是如果我们“手
贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时
候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行,我
们预先设想的清理工程的功能也就无法完成。为了避免这个问题,我们可以将 clean 声明为伪目标

5.14  RAM、ROM、flash、eMMC

RAM:随机存储器,可以读写,断电的时候数据丢失(运行内存)

ROM:只读存储器,不能随意修改,断电的时候数据保存(程序存储器)

ROM掉电数据不丢失,但数据不能随意更新,正是由于该缺点,就有了flash的发展

Flash闪存是属于ROM的一种

EMMc=NAND Flash+闪存控制芯片+标准接口封装

EMM类似于硬盘,将NAND Flash与控制器集成,通过内在的控制器管理Falsh

程序存放在ROM中,运行的时候会江代码搬运到RAM中

单片机与时钟

时钟信号是内部芯片或者外部晶振产生,是单片机的脉搏决定了cpu的频率,时钟信号推动单片机各个部分执行相应的指令。

  • STM32时钟系统主要的目的就是给相对独立的外设模块提供时钟,也是为了降低整个芯片的耗能
  • 一个机器指令一个时钟周期
  • STM32本身十分复杂,外设非常多  但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费   并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。所以便有了STM32的时钟系统和时钟树

通用IO与复用IO

通用IO是指使用GPI0控制引脚的输如输出

复用IO是指使用引脚作为芯片内置外设的功能引脚

一个引脚只能一种复用,不然要使用重映射
通用与复用不能同时存在

5.30 文件挂载

linux系统中的根文件系统数据上层,想要使用下层具体硬盘中的数据资源,需要将硬盘中的空间挂载到linux系统目录中,这样cpu才能通过linux系统根目录去调用硬件资源。


接下来,我们在根目录下新建一个目录 /sdb-u,通过挂载命令将 U 盘文件系统挂载到此目录,挂载效果如图 2 所示。

Linux 系统使用任何硬件设备,都必须将设备文件与已有目录文件进行挂载。

6.6 IO控制

1、时钟开启

2、IO复用(是作用GPIO还是UART的功能引脚之类的)

3、若是复用为GPIO,下一个就是设置GPIO模式(STM32 有八种输入四种,输出四种,linux有些不同但是大概是这样意思)

4、设置GPIO的高低电平(这本质也是对寄存器进行赋值)

6.6 使用visiul studio注意添加头文件

vscode软件设置头文件路径的方法_vscode添加头文件路径-CSDN博客

6.6 ssh,scp 连接

代码学习

#define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)

定义CCM_CCGR0表示0X020C4068地址的值。其中*表示解引用,从地址取到内存。

想要某位置为1,就与1相或,想将某位置为0就与0相并

位置的选择使用左移和右移

与中0,且中1   霸道

GPIO1->GDIR |= (1 << 3);  将GPIO->GDIR 的第四位设置为1

GPIO1->DR &= ~(1 << 3);   将GPIO->GDIR 的第四位设置为0
volatile”进行了修饰,目的是防止编
译器优化。

6.19 git工具的使用

显示出所有的配置文件

git clone config -l

显示系统的配置

git config --system --list

显示用户的配置

git config --global --list

设置用户名和邮箱

git config --global user.name "xxx"

git config --global user.email xxx

每一次提交都会将这个信息上传,如果希望一个项目中使用多个用户名就不用使用global,这样就不设置成全局变量。

6.24 vscode的使用

 进入函数之后的回退 ALT +<-

 全局搜索  ctrl +shift +F

 本文件搜索  ctrl +F

vscode  ctrl + p    终端文件搜索


vscode  ctrl +y     回退修改

怎么选择多行代码??????

 6.27 svn使用

删除文件之后,windows目录下使用svn updata  可以更新文件

删掉的文件,会重新补上。要是想提交新的文件或者删掉一些文件需要使用svn detect ,snv add

svn co  +网站    拉取服务器上的代码

svn co http://localhost/test/testapp --username wzhnsc

在当前目录打开show log 可以看到当前目录下所有文件的每一次文件提交的修改

svn set 里面可以切换账号,点击clear  

6.28 中断查看

cat /proc/interrupts

第一列:IRQ序号

第二、三列:CPU0/CPU1分别是当前CPU上发生中断的次数

第四列:中断控制器名称,比如IO-APIC

最后一列:设备名称,比如timer

要写一个中断程序,就必须要申请一根中断线,一个中断线又对应一个IRQ号

6.30 软件复位与硬件复位

硬件复位操作寄存器来复位

软件复位

调用一个复位函数进行复位


7.2 extern 

extern "C" {
    void myFunction(int);
}

通过使用 extern "C",你告诉 C++ 编译器不要对括号内的函数或变量进行名称重命名,确保它们能够与 C 代码正确链接。

extern int __init os08a10_init(void);

extern: 这个关键字表示 os08a10_init 函数是在当前源文件之外定义的。换句话说,这个函数的实现不在当前文件中,而是在其他某个地方(可能是另一个源文件

7.2 _init 和 __exit 

int __init os08a10_init(void)
{
	int ret;

	if (vinc_id > 0xF) { /* multi vin case, use dt ids to load driver automatically */
		i2c_driver_os08a10.driver.of_match_table = of_match_ptr(os08a10_dt_ids);
	} else {
		ret = ambpriv_i2c_update_addr("os08a10", bus_id, addr);
		if (ret < 0)
			return ret;
	}

	ret = i2c_add_driver(&i2c_driver_os08a10);
	if (ret < 0)
		return ret;

	return 0;
}

void __exit os08a10_exit(void)
{
	i2c_del_driver(&i2c_driver_os08a10);
}

__init: 这是一个特定于编译器的属性或指令,常见于 Linux 内核编程中。__init 标记告诉编译器和链接器,这个函数是初始化函数,仅在系统启动时调用一次。这意味着,一旦初始化完成,这个函数的代码可以从内核的常驻内存中移除,以节省宝贵的内存资源。在 Linux 内核中,__init 和 __exit 是用来标记初始化和清除函数的,它们由内核的初始化机制自动调用

7.2 四种条件编译

1、#if 常量表达式 #endif

#ifdef  ABC //要是        ABC被定义了,也就是说这个if是true,就会执行下面的,将代码加入编译

#else

#endif     表示结束

2.多分支的条件编译
#if 常量表达式
#elif 常量表达式
#else
#endif

3.判断是否被定义的条件编译指令

#if defined(symbol)//等价与右边面的写法                #ifdef symbol
#if !defined(symbol)等价右边的写法            #ifndef symbol

4.嵌套指令

#if defined(OS_UNIX)
    #ifdef OPTION1
        unix_version_option1();
    #endif
    #ifdef OPTION2
        unix_version_option2();
    #endif
#elif defined(OS_MSDOS)
    #ifdef OPTION2
        modos_version_option2();
    #endif
#endif

7.4  UART、RS232、RS485

三者本质上都是基于UART,UART 是基于TTL电平传输,但是RS232、RS485 将TTL电平进行转换成其他电平再进行通信传输。

TTL、RS-232、RS-485则是逻辑电平0和1的不同表示标准,它们区别如下

标准逻辑电平0逻辑电平1是否全双工抗干扰能力
TTL输出低电平<0.4V, 输入低电平<=0.8V输出高电平>2.4V,输入高电平>=2.0V全双工
RS232+3~+15V-3~-15V全双工
RS485+2V~+6V- 6V~- 2V半双工很强
两个设备之间采用RS232通讯

常用的TTL转RS232的电平转换芯片有MAX232,MAX3232。其中MAX232只能用5V供电。而MAX3232可以用5V或3.3V供电。在这里插入图片描述
RS232接口图片如下:
在这里插入图片描述

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值