#山外K60函数 FTM_PWM_…
来源:互联网 发布:淘宝积分有什么用处 编辑:程序博客网 时间:2024/06/04 19:02
void FTM_PWM_Duty(FTMn_e ftmn, FTM_CHn_e ch, uint32duty)
{
注:ASSERT是一个断言,关于断言请看代码结尾的注释1
}
}
注:关于FTM_MOD_REG请看注释2,FTMN[]请看注释3,ftmn请看注释4
default:
}
注释部分
注释1:ASSERT断言
断言就是假设你的判断是对的,这也是英文单词assert的含义。
在C语言里面断言的用法就是“ASSERT(假设正确的判断);”,C语言往往是把断言放在条件编译里面去用的,条件编译是一种预处理,在这个预处理中你可以设置一个断言,如果断言正确,那么就执行程序,如果断言失败,就让系统报错。就是说,设置一个合理的断言,如果你的程序里有错,编译软件在编译前就可以报错,而不是编译软件在程序运行过程中发现了某些不可预知的错误时报错,甚至是崩溃。
举个例子,这个断言中检测数组的引用是否超出了引用的范围,如下:
int a[i];inta=10;//此时你只能引用到a[9]
你可以在条件编译中断言ASSERT(i<10);如果你在主函数中存在a[10],那么条件编译中的断言就失败了,此时可以让软件报错了,主程序也就不会被执行了。
让我们跳到代码中ASSERT的底层看个究竟:
void assert_failed(char *, int);
#if defined(DEBUG )
注:这条语句意思是如果宏定义了DEBUG,开始我理解DEBUG就是DEBUG模式,下面是引用师兄的解释:
DEBUG就是一个宏标识,不一定就是DEBUG模式有时调试的时候,我也会在Release模式中加入宏定义DEBUG,目的就是输出一些调试信息。DEBUG这个宏,它就是一个工具,我需要的时候就用,不需要的时候就注释。因为发布的代码,仅仅是在DEBUG模式中用到,所以你把DEBUG这个宏当作DEBUG模式来看,也没错。(原则上我还是错的)
#defineASSERT(expr) \
if(!(expr))\
注:如果expr是假(断言失败),即!expr是真,则执行断言失败函数,如果expr是
真(断言成功),则不执行断言失败函数,直接进入主程序。
#else
#defineASSERT(expr)
#endif
void assert_failed(char *file, int line)
{
}
}
#if(defined(DEBUG) && defined(DEBUG_PRINT))
#define
#else
#define DEBUG_PRINTF(FORMAT,...)
#endif
注释2:FTM_MOD_REG(base)
#define
这是一个宏定义,看来base是一个地址,意思是将base地址指向的MOD替换成FTM_MOD_REG(base)
注释3:FTMN[]
跳到定义处:
FTM_MemMapPtr FTMN[3] = {FTM0_BASE_PTR, FTM1_BASE_PTR,FTM2_BASE_PTR};
这是一个指针数组,为什么是指针数组呢,那么就得看看FTM_MemMapPtr这个关键词是什么意思了,请看下面的底层:
typedef struct FTM_MemMap
uint32_t CnV } CONTROLS[8];
uint32_tMODE;
uint32_tPOL;
uint32_tFLTPOL;
uint32_tINVCTRL;
} volatile *FTM_MemMapPtr;
这个语句的意思是把FTM_MemMapPtr定义为结构体指针,其实它是上述那一大串结构体指针的一个别名,这是通过typedef这个关键字实现的。
注:typedef是存储类型的关键字,意思是它占用内存,可以发现typedef是一条语句,后面是有分号的,这一点是与宏定义不同的,宏定义是预处理,不占用内存,这就体现宏定义的优点了,宏定义用的多了,仅仅加长编译的时间,对运行是没有影响的。
下面跳入FTMN[3]数组中的FTM0_BASE_PTR:
#define
宏定义将((FTM_MemMapPtr)0x40038000u)替换成FTM0_BASE_PTR,因为FTM0_BASE_PTR在主程序里面是一个地址,那么((FTM_MemMapPtr)0x40038000u)应该也是一个地址,0x40038000u只代表一个数,编译软件是不会把它当做地址的,但是(FTM_MemMapPtr)0x40038000u意思是把0x40038000u强制转换为地址,这样就可以用宏定义了。
下面是我对为什么要进行强制转换地址的理解:
请看下面两条语句
第一句:FTM_MemMapPtrFTMN[3] = {FTM0_BASE_PTR, FTM1_BASE_PTR, FTM2_BASE_PTR};
其实,这两句话是一样的。
第一句中用了个宏定义,宏定义是一种预处理,此时FTM0_BASE_PTR还没有被指定类型,宏定义只是替换作用,此时编译器并不知道0x40038000u是一个地址,所以需要强制转换;
第二句用了一个赋值语句,因为编译器知道FTM0_BASE_PTR是一个地址,所以直接给它赋值就行了,而不用强制转换;
之所以不用赋值而用宏定义“仅仅是为了简化代码编写,增强可阅读性和可移植性。并不是为了省空间”,这是山外哥说的。
注释4:FTMn_e
跳到FTMn_e
typedef enum
{
} FTMn_e;
这是一个枚举,然后把这个枚举替换成FTMn_e这个别名,但是枚举里面的成员是FTM0,
FTM1, FTM2,FTM_MAX,但是这个语句中的FTMN[ftmn]是一个数组,数组后面的括号里面不应该是数字123吗,因为编译器会为枚举里面的成员自动赋值:如果是首枚举成员,则赋值为0,以此类推,所以FTMN[FTM0]就是FTMN[0]。、
注:原创博文,引用请注明出处,本博文代码源自山外提供的K60代码
- #山外K60函数 FTM_PWM_…
- K60 first GPIO
- K60 ADC
- K60 PIT定时器
- K60 GPIO外部中断
- 飞思卡尔K60 FTM模块详…
- 飞思卡尔K60 FTM模块详…
- 飞思卡尔Kinetis 60(K60)时钟…
- matlab dist函数 …
- (Kinetis K60)WDOG看门狗测试
- 指针函数 函数指…
- 【MATLAB】matlab eig 函数…
- libsvm 核函数 交…
- MATLAB中的eye() 函数 …
- MATLAB fgoalattain()函数 解…
- Matlab dlmwrite函数 将…
- matlab lsqcurvefit函数&nbsp…
- matlab sort() 排序函数…
- Spark+Hadoop环境搭建
- ExpandableListView(手风琴)(2)---CursorTreeAdapter(数据库)
- *(volatile unsigned long *) 语法
- #C数据结构 联合体union
- oracle 设置归档模式
- #山外K60函数 FTM_PWM_…
- #C运算符 位运算符
- 【每日一题】 -1和1的数值比较
- 【每日一题】 优先级、左移问题
- css实现鼠标上移图标旋转效果
- 【每日一题】 -1和1的数值比…
- 舵机的原理和控制
- com.android.ide.common.signing.KeytoolException:Failed to read key meihuo from store
- 表达式树的值