打印

单片机C编程,,,持续更新

[复制链接]
2241|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
关于单片机C编程:
after three days without programming ,life becomes meaningless.

if the program fails in these requirements ,it will be in a state of disorder and confusion
the only way to correct this is rewrite the program.


首先不管建立任何新的工程都必须包含这几个文件夹
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<<BitOffset))//设置某位
#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];
                                       

相关帖子

沙发
lxj19901115|  楼主 | 2013-7-18 15:39 | 只看该作者
                        要解释这段代码要知道下面这些东西
                        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的数组
                        既然是数组,那么就可以使用下标的形式来对数组内存储的元素进行读写访问。

使用特权

评论回复
板凳
lxj19901115|  楼主 | 2013-7-18 15:47 | 只看该作者
文件组织如图:

33EW}L@74(~JFUG_G}JH}NH.jpg (37.62 KB )

33EW}L@74(~JFUG_G}JH}NH.jpg

使用特权

评论回复
地板
xyz549040622| | 2013-7-18 22:03 | 只看该作者
给lz顶起

使用特权

评论回复
5
lxj19901115|  楼主 | 2013-7-18 22:57 | 只看该作者
接着继续更新,关于指针,
代码入下:
         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库里面的架构,
         相信会给你带来很多灵感,

使用特权

评论回复
6
lxj19901115|  楼主 | 2013-7-18 23:09 | 只看该作者
[size=13.63636302947998px]#include <glib_use.h>



[size=13.63636302947998px]u16 gb_LCD_X_Size,gb_LCD_Y_Size;

[size=13.63636302947998px]void DebugDisp_AChar(void);
[size=13.63636302947998px]void DebugDisp_CharAt(void);
[size=13.63636302947998px]void DebugDisp_Chars(void);
[size=13.63636302947998px]void DebugDisp_NextLine(void);
[size=13.63636302947998px]void DebugDisp_String(void);
[size=13.63636302947998px]void DebugDisp_StringAt(void);
[size=13.63636302947998px]void DebugDisp_StringAtCEOL(void);
[size=13.63636302947998px]void DebugDisp_StringHCenterAt(void);
[size=13.63636302947998px]void DebugDisp_StringInRect(void);
[size=13.63636302947998px]void DebugDisp_StringInRectEx(void);
[size=13.63636302947998px]void DebugDisp_InRectWarp(void);
[size=13.63636302947998px]void DebugDisp_StringLen(void);
[size=13.63636302947998px]void DebugDisp_WrapGetNumLines(void);
[size=13.63636302947998px]void DebugDisp_GetTextMode(void);
[size=13.63636302947998px]void DebugDisp_SetTextMode(void);
[size=13.63636302947998px]void DebugDisp_SetTextStyle(void);
[size=13.63636302947998px]void DebugDisp_GetTextAlign(void);
[size=13.63636302947998px]void DebugDisp_SetLBorder(void);
[size=13.63636302947998px]void DebugDisp_SetTextAlign(void);
[size=13.63636302947998px]void DebugDisp_GotoX(void);
[size=13.63636302947998px]void DebugDisp_GotoY(void);
[size=13.63636302947998px]void DebugDisp_GotoXY(void);
[size=13.63636302947998px]void DebugDisp_GetPosX(void);
[size=13.63636302947998px]void DebugDisp_GetPosY(void);
[size=13.63636302947998px]void DebugDisp_Clear(void);
[size=13.63636302947998px]void DebugDisp_CEOL(void);


[size=13.63636302947998px]void (*pDebugHandler[])(void)=
[size=13.63636302947998px]{
[size=13.63636302947998px]        DebugDisp_AChar,
[size=13.63636302947998px]        DebugDisp_CharAt,
[size=13.63636302947998px]        DebugDisp_Chars,
[size=13.63636302947998px]        DebugDisp_NextLine,
[size=13.63636302947998px]        DebugDisp_String,
[size=13.63636302947998px]        DebugDisp_StringAt,
[size=13.63636302947998px]        DebugDisp_StringAtCEOL,
[size=13.63636302947998px]        DebugDisp_StringHCenterAt,
[size=13.63636302947998px]        DebugDisp_StringInRect,
[size=13.63636302947998px]        DebugDisp_StringInRectEx,
[size=13.63636302947998px]        DebugDisp_InRectWarp,
[size=13.63636302947998px]        DebugDisp_StringLen,
[size=13.63636302947998px]        DebugDisp_WrapGetNumLines,
[size=13.63636302947998px]        DebugDisp_GetTextMode,
[size=13.63636302947998px]        DebugDisp_SetTextMode,
[size=13.63636302947998px]        DebugDisp_SetTextStyle,

[size=13.63636302947998px]};



[size=13.63636302947998px]void Sys_emWIN_Init(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        gb_LCD_X_Size = LCD_GetXSize();
[size=13.63636302947998px]        gb_LCD_X_Size =  LCD_GetYSize();
[size=13.63636302947998px]        GUI_SetBkColor(GUI_BLUE);
[size=13.63636302947998px]        GUI_Clear();
[size=13.63636302947998px]        GUI_SetColor(GUI_RED);
[size=13.63636302947998px]        GUI_SetFont(&GUI_Font24_ASCII);
[size=13.63636302947998px]}
[size=13.63636302947998px]void MainTask(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        int gb_DebugNum;
[size=13.63636302947998px]        GUI_Init();
[size=13.63636302947998px]        Sys_emWIN_Init();
[size=13.63636302947998px]        gb_DebugNum = 0;
[size=13.63636302947998px]        (*pDebugHandler[gb_DebugNum])();
[size=13.63636302947998px]        while(1);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_AChar
[size=13.63636302947998px]在当前位置显示一个字符
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_AChar(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispChar(0x32);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_CharAt
[size=13.63636302947998px]在指定的位置显示一个字符
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_CharAt(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        U16 tw_X,tw_Y;
[size=13.63636302947998px]        tw_X = gb_LCD_X_Size / 2;
[size=13.63636302947998px]        tw_Y = gb_LCD_Y_Size / 2;
[size=13.63636302947998px]        GUI_DispCharAt('a',tw_X,tw_Y);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_Chars
[size=13.63636302947998px]在当前位置连续显示某个字符
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_Chars(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispChars('a',5);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_NextLine
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_NextLine(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispChar(0x32);
[size=13.63636302947998px]        GUI_DispNextLine();
[size=13.63636302947998px]        GUI_DispCEOL();
[size=13.63636302947998px]        GUI_DispChar(0X33);

[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_String
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_String(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_GotoXY(100,100);
[size=13.63636302947998px]        GUI_DispString("FUCK YOU!");
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringAt
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringAt(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispStringAt("Fuck you",100,100);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringAtCEOL
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringAtCEOL(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispStringAtCEOL("Fuck you",100,100);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringHCenterAt
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringHCenterAt(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]        GUI_DispStringHCenterAt("cao nima ",100,100);
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringInRect
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringInRect(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]#if 1
[size=13.63636302947998px]        LCD_RECT tw_Rect;
[size=13.63636302947998px]        tw_Rect.x0 = 0;
[size=13.63636302947998px]        tw_Rect.y0 = 0;
[size=13.63636302947998px]        tw_Rect.x1 = 100;
[size=13.63636302947998px]        tw_Rect.y1 = 100;
[size=13.63636302947998px]        GUI_GetClientRect(&tw_Rect);
[size=13.63636302947998px]        GUI_DispStringInRect("fuck you mama ",&tw_Rect,GUI_TA_TOP | GUI_TA_LEFT);
[size=13.63636302947998px]#else
[size=13.63636302947998px]        GUI_RECT rClient;

[size=13.63636302947998px]        GUI_GetClientRect(&rClient);
[size=13.63636302947998px]        GUI_DispStringInRect("fuck you mama ",&rClient,GUI_TA_TOP | GUI_TA_LEFT);
[size=13.63636302947998px]#endif
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringInRectEx
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringInRectEx(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_InRectWarp
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_InRectWarp(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_StringLen
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_StringLen(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_WrapGetNumLines
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_WrapGetNumLines(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_GetTextMode
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_GetTextMode(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_SetTextMode
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_SetTextMode(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}
[size=13.63636302947998px]/***************
[size=13.63636302947998px]DebugDisp_SetTextStyle
[size=13.63636302947998px]****************/
[size=13.63636302947998px]void DebugDisp_SetTextStyle(void)
[size=13.63636302947998px]{
[size=13.63636302947998px]}



使用特权

评论回复
7
lxj19901115|  楼主 | 2013-7-18 23:13 | 只看该作者
关于上面的那段代码,这个是我在玩emWIN的时候所写的对于里面的API的测试文件
亮点在这里:
void MainTask(void)
{
        int gb_DebugNum;
        GUI_Init();
        Sys_emWIN_Init();
        gb_DebugNum = 0;
        (*pDebugHandler[gb_DebugNum])();
        while(1);
}

此文件中使用了,指针函数数组,void (*pDebugHandler[])(void),所以在调试的时候只需要gb_DebugNum改变,就可以对这个文件里面,MainTask下面的任意函数进行调用,可以减少代码量,非常适合测试代码,,,

使用特权

评论回复
8
蓝魔大师弟| | 2013-8-8 17:30 | 只看该作者
学习,学习

使用特权

评论回复
9
邓5566| | 2013-8-23 11:20 | 只看该作者
LZ顶起来!

使用特权

评论回复
10
568581185| | 2013-8-23 14:39 | 只看该作者
顶上。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

94

帖子

1

粉丝