|
首先不管建立任何新的工程都必须包含这几个文件夹
1 Code 存放你的代码文件夹
2 SCH 存放你的原理图和PCB图
3 DOC 工程说明文档
4 RESOURCE 包含在这个工程里面所使用的芯片说明,音源,或者烧录文件,外部存储档
5 RELEASE 包含最终程序烧录档,原理图,升级文件等等
并且在项目文件夹名字,必须对应的工程名字,末尾加上版本号如:GP6000_LED_V1.0
user_define.c//包含所使用的全局变量的声明,并包含所使用的系统控制变量的初始化函数Sys_VariableInit();
user_define.h//包含了整个工程中所使用的全局变量的外部声明和宏定义
在这个文件夹里面,我比较常用的有以下几个宏
#define Glib_SetValueBit(Value,BitOffset) (Value |= (1<
#define Glib_ClrValueBit(Value,BitOffset) (Value &=~(1 << BitOffset))//清除某位
#define Glib_ReadValueBit(Value,BitOffset) (Value &(1 << BitOffset))//读取某位
#define Glib_GetCountOf(a) (sizeof(a) / sizeof(a[0]))//得出缓冲区元素个数
#define Glib_GetMIN(a,b) (((a) < (b)) ? (a) : (b))//读取最小元素
#define Glib_GetMAX(a,b) (((a) > (b)) ? (a) : (b))//读取最大元素
#define Glib_GetZEROFILL(p, Size) (memset(p, 0, Size)) //清除缓冲区
user_type.h//根据自己编写代码的风格定义数据类型
extern_fun.h//外部函数声明
第二,使用模块化思维,架构整个工程。
比如,在这个工程里面使用了GPS模块,那么在你的代码文件夹里面必须包含这两个文件Gps.c 和Gps.h
第三关于函数,变量,宏的命名规则
全局变量 g_VariableName 比如定义一个64Hz的定时器变量u32 g_Timer64HZ_Flag
一看到这个变量就知道,这一个定时器标志位变量,而且频率为64Hz,标志的间隔为16ms
定义一个指向串口接收缓冲区的指针如u8 *gP_Uart3RxBuffer;
定义一个串口接收缓冲区 u8 g_Uart3RxBuffer,并定义偏移量u16 g_Uart3RxOffset;
局域变量 tw_variablename
宏定义 常数定义 #define c_ConstName ConstValue
函数操作 #define Handler_Name {....;}
第三,关于C语言指针,数组
首先明确在使用指针两个核心点:
1 所指向的地址是多少
2 偏移量的基本单位
比如 要取出 一个u16 g_ADC3Value 的变量里面的,高八位,保存在变量u8 tw_calADC;里面
看到这个,一般人的思维是这样的操作代码如下 tw_calADC = ((g_ADC3Value >> 8) && 0xFF);
使用移位操作,用汇编的思维
但是如果让我来写的话,
代码如下:tw_calADC = ((u8 *)(&g_ADC3Value))[1];
要解释这段代码要知道下面这些东西
1,单片机内存的最基本的单位是byte,所以g_ADC3Value 这个变量在内存中存储的时候所占用的内存空间为2个Byte
2,明白了第一条,你还需要明白这样一个东西,任何变量在内存中都是有地址的,那么你就可以把g_ADC3Value 这个变量看成一个数组
数组名字为g_ADC3Value,元素为2,基本单位是Byte
明白了这两点那么,来看这段代码
(&g_ADC3Value) 此操作为取变量g_ADC3Value 在内存中的地址
(u8 *) 对上步所取得的地址以一个Byte的宽度去访问,实际上是把g_ADC3Value 分成两段
[1],使用数组下标的形式去提取这个数组内的元素
((u8 *)(&g_ADC3Value))[1]; 整句话的意思就是,将变量g_ADC3Value所存储的东西强制转换为一个数据类型为unsigned char 数据宽度为2的数组
既然是数组,那么就可以使用下标的形式来对数组内存储的元素进行读写访问。
接着继续更新,关于指针,
代码入下:
u32 gb_PlayFilesIndex;
gb_PlayFilesIndex = 0x12345678;
u8 temparray[4];
for(u8 i = 0;i < 4;i++)
{
temparray[i] = ((u8*)(&gb_PlayFilesIndex))[i];
}
看到这段代码,你能立即写出temparray数组里面所存的数据吗?
如果不能,那就听我分析:
比如运行这段代码的是一颗32位的ARM处理器,
gb_PlayFilesIndex 它的内存地址 是0x20000000;
谈到这里,你要明白不管它是什么处理器或者内存单元,最基本的单位是 BYTE,字节,所以如你自己写过内存操作函数的话,大概会这么写
void MemSet(void *pBuffer,u8 data,u16 size)
{
u8 *p_databuffer = *pBuffer;
u16 i = 0;
while(i < size)
{
*(p_databuffer+(i++)) = data;
}
}也许有人会说为什么不用for语句,一般的来说,从反汇编的角度来说,使用while比for的效率要高
那么在存储gb_PlayFilesIndex,这个数据的时候,这个数据它所占据的内存单元就是有四个
不管是什么变量,它都包含两个最基本的元素:它所代表的数据,和它所在内存中的地址,所以你在使用IDE的WATCH功能的时候,一般都有三个最基本的元素 变量名 地址 数据
temparray[i] = (u8*)(&gb_PlayFilesIndex)[i]; 看这句代码的等号后面的部分,根据C里面的运算符号的优先级,
(u8*) 首先是这部分称之为A,是将在这个表达式后面的数据强制转换为 U8*类型的指针
(&gb_PlayFilesIndex) 这部分称之为B,是取gb_PlayFilesIndex在内存中起始地址的地址,而这个地址就是0x20000000
[i] 这部分称之为C,使用的是数组下标格式引用数据
temparray[i] = (u8*)(&gb_PlayFilesIndex)[i];
这句代码,首先是将gb_PlayFilesIndex 所在的内存地址,强制转换为 U8 类型的指针,而这个指针所指向的是内存地址是0x20000000的地址,那么这个地址内所存的数据
就是temparray[0] = 0x78,一般是这个样子,而这中存储方式称为小端存储,如果是大端的话,那么这个0x20000000 地址内存的就是temparray[0] =0x12了,
那么有人会想到这个,为什么要带个数组下标的方式[i]呢,
那么可以打个比方,一个地址为0x20000000的盒子里面存放的数据是0x12345678,那么在这个0x20000000的盒子里面分为了4个最基本的小盒子
你要明白不管是它是怎么存储数据的,但是必须尊崇的规则那就是所存储的数据方式都必须是连续存储的,存储单位是以BYTE为方式,如果不是连续的存储的话,那么C里面为什么还要加入指针的概念呢
说到连续存储,那么你就会想到大学里面C语言老师在跟你讲数组的时候,数组在内存中的本质是什么,好好想想,,,
想明白了,那么就会明白这段代码,所做的处理是什么,(u8*)(&gb_PlayFilesIndex)[i] 首先是将变量gb_PlayFilesIndex看成一个数据宽度是4,存储单位为一个BYTE的数组,而这个数组的名字就是gb_PlayFilesIndex
当你把这个变量看成数组的时候,那么想访问数组里面的元素,就可以通过下标的方式来访问,而访问的单位为一个BYTE
为什么弄这个代码呢,因为我们在写程序和处理数据的时候,很多时候要把数据拆开来,一般的方式就是通过移位来得到,如果用这种方法写的话,那么不需要什么移位操作,直接提取数据,就可以了,,这样做相对来说是做些小小的优化
故以小端数据对齐方式的:
0x20000000 temparray[0]= 0x78;
0x20000001 temparray[1]= 0x56;
0x20000002 temparray[2]= 0x34;
0x20000003 temparray[3]= 0x12;
大端的反推过来就是了,
那么你再看看这段代码:
typedef struct
{
u8 num1;
u8 num2;
}TEST_P;
TEST_P test;
test.num1 = 1;
test.num2 = 2;
printf("%d,%d",test.num1,test.num2);
(TEST_P*)(&test)[1] = 7;
printf("%d",test.num2);
(TEST_P*)(&test)[1])[1] = 9;
printf("%d,%d",test.num1,(TEST_P*)(&test)[1])[1]);
你能回答出第二个打印函数 打印的数据是多少吗?
第三个打印出来又是什么,
当你把这部分解答出来了,那么你就可以想想结构体在内存中的本质是什么,,如果你想对结构体部分多了解些的话,你可以去看看STM32 USB库里面的架构,
相信会给你带来很多灵感,
|
赞赏
-
1
查看全部赞赏
-
|