如果要写个延时程序,是用 for(i=0;i<100;i++); 还是用 for(i=100;i>0;i--);
似乎没什么区别,但在汇编里面用加一的思想,程序必然这么写,
mov r0,#00H ;2字节
loop:
inc r0 ;1字节
cjne r0,#64H,loop ;3字节
如果用减一的思想,程序可以这么写
mov r0,#64H ;2字节
loopL:
djnz r0,loop ;2字节
其实这也是keil c对C处理后的汇编情况。 由此可见,C的语法稍微变一点,就可以节约2个byte,定时可以更精确。 程序更简洁!
C51提供的本征函数是指编译时直接将固定的代码插入当前行,而不是用ACALL和LCALL语句来实现,这样就大大提供了函数访问的效率,
而非本征函数则必须由ACALL及LCALL调用。 C51的本征库函数只有9个,数目虽少,但都非常有用,列如下:
unsigned char _crol_(unsigned char c,unsigned char b);
//字符循环左移
unsigned char _cror_(unsigned char c,unsigned char b);
//字符循环右移
unsigned char _chkfloat_(float ual);
unsigned int _irol_(unsigned int i,unsigned char b);
//整数循环左移
unsigned int _iror_(unsigned int i,unsigned char b);
//整数循环左移
unsigned long _lrol_(unsigned long l,unsigned char b);
//长整数循环左移
unsigned long _lror_(unsigned long L,unsigned char b);
//长整数循环右移
void _nop_(void);
//空操作8051 NOP 指令
bit _testbit_(bit b);
//测试并清零位8051 JBC 指令
使用时,必须包含#inclucle <intrins.h>一行。
如不说明,下面谈到的库函数均指非本征库函数。
1. CTYPE.H
bit isalnum(char c);
bit isalpha(char c);
bit iscntrl(char c);
bit isdigit(char c);
bit isgraph(char c);
bit islower(char c);
bit isprint(char c);
bit ispunct(char c);
bit isspace(char c);
bit isupper(char c);
bit isxdigit(char c);//若参数为16进制数字返回1,否则返回0
bit toascii(char c);
//return(c & 0x7f);
//将字符转换为ascii码。将字符c的高位清零,仅保留低七位。返回转换后的数值。
bit toint(char c);
char tolower(char c);
char __tolower(char c);
char toupper(char c);
char __toupper(char c);
// s convert to lowercase
for (p = s; *p; p++) {
*p = tolower (*p);
}
// Remove path info from filename, keep only the name. dat为原数据, var=转换后数据
U8 *var, *p;
var = dat;
for (p = dat; *p; p++) {
if ((*p == '\\') || (*p == '/'))
var = p + 1;
}
for(; (ty<Height) && (ty>=0); ty+=Step) {
//首个条件为空.
3. STDIO.H
char getch(void);
char getchar(void);
char _getkey(void);
char *gets(char * string,int len);
int printf(const char * fmtstr[,argument]…);
char putchar(char c);
int puts (const char * string);
int scanf(const char * fmtstr.[,argument]…);
int sprintf(char * buffer,const char *fmtstr[;argument]);
//必须先给buffer分配内存. 如char buffer[12]
int sscanf(char *buffer,const char * fmtstr[,argument]);
//从一个字符串中读进与指定格式相符的数据
U8 *var,i;
int s[4];
sscanf ((const char *)&var[3], "%d.%d.%d.%d",&s[0],&s[1], &s[2],&s[3]);
sscanf(sztmp, "%X", &tmp);
//将十六进制的字符串 ==> 十进制数
char ungetchar(char c);
void vprintf (const char *fmtstr,char * argptr);
void vsprintf(char *buffer,const char * fmtstr,char * argptr);
#define SEEK_SET 0 /* start of stream (see fseek) */
#define SEEK_CUR 1 /* current position in stream (see fseek) */
#define SEEK_END 2 /* end of stream (see fseek) */
i = sprintf(Buf, "%02bx/",RfOutTime.month);
i+= sprintf(Buf+i,"%02bx/",RfOutTime.date);
i+= sprintf(Buf+i,"%02bx ",RfOutTime.year);
i+= sprintf(Buf+i,"%02bx:",RfOutTime.hr);
i+= sprintf(Buf+i,"%02bx\0",RfOutTime.min);
//--- 将8字节的数据变成HEX
strcpy(pcID, "Data = ");
Pos = strlen(pcID);
for(i=0; i<8; i++) {
Pos += sprintf(pcID+Pos, " %02X", pbAttr[i]);
//后判断长度
}
4. STDLIB.H
float atof(void * string);
//把字符串转换成浮点数
int atoi(void * string);
// 把字符串转换成整型数
char *itoa(int value, char *string, int radix);
int value 被转换的整数,char *string 转换后储存的字符数组,int radix 转换进制数,如2,8,10,16 进制等
long atol(void * string);
//把字符串转换成长整型数
void * calloc(unsigned int num,unsigned int len);
void init_mempool(void *data *p,unsigned int size);
void *malloc (unsigned int size);
//申请内存
void free(void xdata *p);
//释放内存
void *realloc (void xdata *p,unsigned int size);
void srand (int seed);
int rand(void);
malloc 函数在 malloc.c 中定义,它实际上是调用 malloc_from_heap 从空闲区域中申请空间
malloc_from_heap 中调用了两个重要的函数,以下分别作解读。
__heap_alloc函数,位于 heap_alloc.c,这个函数的作用就是从空闲区域链表中找到满足条件的节点,同时它会修改参数中的 size,返回实际分配的空间大小:
如果第一次申请空间不成功,就会向系统申请空间,通过 __heap_free 加入到 heap 的空闲区域链表中。
__heap_free 在 heap_free.c 中被定义,它将指定的内存区域加入链表:
srand(56);
//初始化种子,以后就可以直接调用rand()就得到随机数(4字节的无符号数,如1736862005)
dfTemp1 = 10.28 + rand() % 256;
dfTemp2 = 50.16 + rand() % 256;
5. STRING.H
void *memccpy (void *dest,void *src,char c,int len);
void *memchr (void *buf,char c,int len);
char memcmp(void *buf1,void *buf2,int len);
void *memcpy (void *dest,void *SRC,int len);
memcpy(ucSend, "\x80\x88\x00\x20", 4);
memcpy(&MfComData.MfData[2], uid, 8);
void *memmove(void *dest,void *src,int len);
memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
void *memset (void *buf,char c,int len);
char szText[64];
memset(szText,0x00,sizeof(szText));
char *strchr (const char *string,char c);
//在字符串中搜索指定字符。第一个形参就是要搜索的字符串,第二个是被搜索的字符。
//如果找到了该字符就返回该字符第一次出现的内存地址。如果没有找到就返回NULL(也就是0)。
char strcmp (char *string1,char *string2);
//两个字符串相等返回0,第一个大于第二个返回>0的数,否则返回<0的数.
char *strcpy (char *dest,char *src);
//用此函数时, 必须先分配内存. 如char pcTitle[20];
static char buffer[UH_LIMIT_MSGHEAD];
//先用数组分配内存, 再定义指针以方便相关函数的应用
char *bufptr = &buffer[0];
int strcspn(char *src,char * set);
int strlen (char *src);
//参数可为汉字, 如"感谢党感谢政府", len = 14; "感谢1党感谢2政府", len = 16
char ac[50];
strcpy(ac + strlen(ac), "\npressed");
//直接在ac的后面添加字符串.
char *strcat (char *dest,char *src);
//把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
char *strncat (char *dest,char *src,int len);
//把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
char strncmp(char *string1,char *string2,int len);
//只比较前面的len长度的
char strncpy (char *dest,char *src,int len);
char *strpbrk (char *string,char *set);
int strpos (const char *string,char c);
char *strrchr (const char *string,char c);
char *strrpbrk (char *string,char *set);
int strrpos (const char *string,char c);
int strspn(char *string,char *set)
char *strpbrk (char *s, char *set);
char *strrpbrk (char *s, char *set);
char *strstr (char *s, char *sub);
//if (strstr(buffer, "GET /?action=stream") != NULL)
//在s串中查找sub字符串的第一次出现,返回指向第一次出现sub字串位置的指针,若没找到则返回NULL
char *strtok (char *str, const char *set);
//str:要分割的字符串, set: 包含在分割字符串中的字符都会被当做是分割字符而丢弃掉。
char **ppURI;
*ppURI = "/404.html";
//--- 新定义3个指针. 指针指向另外的指针时不能加上运算. dat = (p++)则Err????
pair = strchr(pair, 0x0d);
if(pair) {
*pair = '\0';
//把本位置变为字串结束符, 保证了 ConfigParmValue 的有效
pair++;
dat = p;
// dat = (p++)则Err????
if(*pair == 0x0a){
pair++;
//指向下段起始处
} else{
pair--;
*pair = 0x0d;
//恢复原值
}
}
//WIFI中的httpd.c
char *params, *pcTmp;
params = strchr(params, '&');
if(params) {
params -= 20;
DEBUGP("params -20 = %s\n", params);
//多个\r\n, 移动到最后字节处
while(params) {
params = strstr(params, "\r\n");
if (params) {
params += 2;
pcTmp = params;
}
else break;
}
params = pcTmp;
DEBUGP("params 2 = %s\n", params);
pcTmp = strstr(params, "\r\n");
if (pcTmp) {
*pcTmp = '\0';
}
}
char *pcTmp;
U8 *p, *var;
//g_pucCommonBuf1 = g_pucCommonBuf;
//为同块内存区
strcpy(g_pucCommonBuf1, g_pucCommonBuf);
//必须如此防止原缓冲区数据被修改
var = g_pucCommonBuf1;
pcTmp = strstr((char *)var, pcTitle);
if (pcTmp) {
p = (U8 *)strchr(pcTmp, '&');
if (p) {
*p = '\0';
}
strcpy(g_pucCommonBuf1, pcTmp);
}
//从ip字串中提取ip的参数.
m_edit2.GetWindowText(pcIP, 16);
pair = pcIP;
Pos = 0;
while(pair) {
param = pair;
pair = strchr(pair, '.');
if(pair) {
*pair = '\0';
ucIP[Pos] = atoi(param);
Pos ++;
pair ++;
if(Pos == 3)
ucIP[3] = atoi(pair);
//最后1个无.
}
}
//仅仅改变reg中的mask的特殊位的值为val.
s8 as3910ModifyRegister(u8 reg, u8 mask, u8 val)
{
s8 err;
u8 tmp;
/* make this operation atomic */
IRQ_INC_DISABLE();
err = as3910ReadRegister(reg, &tmp);
if (ERR_NONE == err)
{
/* mask out the bits we don't want to change */
tmp &= ~mask;
/* set the new value */
tmp |= (mask & val);
err = as3910WriteRegister(reg, tmp);
}
IRQ_DEC_ENABLE();
return err;
}
U8 *var,*p;
var = dat;
/* Remove path info from filename, keep only the name. */
for (p = dat; *p; p++) {
if ((*p == '\\') || (*p == '/'))
var = p + 1;
}