1、关于 1602 显示很多字母uchar code cdis1 = “ Red Control “;uchar code cdis1 = “ Red Control “;/貌似这样也可以while(cdis1m != 0) /显示字符lcd_wdat(cdis1m);m+;Volatile 的用法volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与 volatile变量有关的运算,不要进行编译优化,以免出错,(VC+ 在产生 release 版可执行码时会进行编译优化,加 volatile 关键字的变量有关的运算,将不进行编译优化。)。 例如: volat
2、ile int i=10; int j = i; . int k = i; volatile 告诉编译器 i 是随时可能发生变化的,每次使用它的时候必须从 i 的地址中读取,因而编译器生成的可执行码会重新从 i 的地址读取数据放在 k 中。而优化做法是,由于编译器发现两次从 i 读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 k 中。而不是重新从 i 里面读。这样以来,如果 i 是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问,不会出错。上面说的很清楚,补充一下,就是例如定义 i 是定时器的计数值,如果不定义为 v
3、olatile型数据,如果下面有这个语句 int k=I; int j=I; 在这个程序中编译的时候首先会i 所在存储单元中的数据取出来然后送给 k,然后程序继续执行,发现又要去除 i 所在存储单元中的数据,由于编译器发现 i 的值并没有发生变化,记住是以编译器的角度来看,编译器不会考虑到硬件的变化的,所以编译器就不会去 i 所在的存储单元将 i 取出来,而是只会把之前取出的值直接付给 j 了。想想会导致什么样的后果。这样的话如果使用了这个参数来修饰数据的话就可以防止编译器的自动优化。所以我们发现这个参数多用于修饰寄存器变量#define MicroWait(t) Onboard_wait(t
4、) 这个是允许的NEW 关于结构体非常好const SimpleDescriptionFormat_t SampleApp_SimpleDesc =/注意表示这个参数是个只读变量SAMPLEAPP_ENDPOINT, / int Endpoint;SAMPLEAPP_PROFID, / uint16 AppProfId2;SAMPLEAPP_DEVICEID, / uint16 AppDeviceId2;SAMPLEAPP_DEVICE_VERSION, / int AppDevVer:4;SAMPLEAPP_FLAGS, / int AppFlags:4;SAMPLEAPP_MAX_CLUS
5、TERS, / uint8 AppNumInClusters;(cId_t *)SampleApp_ClusterList, / uint8 *pAppInClusterList;SAMPLEAPP_MAX_CLUSTERS, / uint8 AppNumInClusters;(cId_t *)SampleApp_ClusterList / uint8 *pAppInClusterList;而/ Simple Description Format Structuretypedef structbyte EndPoint;uint16 AppProfId;uint16 AppDeviceId;b
6、yte AppDevVer:4;byte Reserved:4; / AF_V1_SUPPORT uses for AppFlags:4.byte AppNumInClusters;cId_t *pAppInClusterList;byte AppNumOutClusters;cId_t *pAppOutClusterList; SimpleDescriptionFormat_t;下面是一个非常经典的关于 struct 的使用方法,通过这个可以优化算法#define GPIOA (GPIO_TypeDef *) GPIOA_BASE)#define APB2PERIPH_BASE (PERIP
7、H_BASE + 0x10000)#define PERIPH_BASE (uint32_t)0x40000000)#define _IO volatile /使用 volatile 来定义寄存器typedef struct /我们看到了使用 typedef 定义了一个结构体_IO uint32_t CRL; /_IO uint32_t CRH;_IO uint32_t IDR;_IO uint32_t ODR;_IO uint32_t BSRR;_IO uint32_t BRR;_IO uint32_t LCKR; GPIO_TypeDef;通过上面这样的使用就可以不用再一步步的UART 的
8、使用_SZ_STM32_COMInit(COM, / 调用 STM32 的 USART 初始化底层函数printf(“rnnnr WWW.ARMJISHU.COM %s printf configured.“, (COM = COM1)? SZ_STM32_COM1_STR:SZ_STM32_COM2_STR);printf(“nr # WWW.ARMJISHU.COM! # (“_DATE_ “ - “ _TIME_ “)“);printf(“%s“, STM32F10x_STR);printf(“ WWW.ARMJISHU.COM use _STM32F10X_STDPERIPH_VERS
9、ION %d.%d.%d“,_STM32F10X_STDPERIPH_VERSION_MAIN,_STM32F10X_STDPERIPH_VERSION_SUB1,_STM32F10X_STDPERIPH_VERSION_SUB2);printf(“nr 产品内部 Flash 大小为:%dK 字节! t “,*(_IO uint16_t*)(0x1FFFF7E0);SystemCoreClockUpdate();printf(“nr 系统内核时钟频率(SystemCoreClock)为:%dHz.nr“,SystemCoreClock);char ssid=“STC89LE52“; /网络名称
10、 ,用户可随自己需要设置char key=“01234567“; / 网络 密码 01234567memset (set.ssid,0,sizeof(set.ssid); /更改 SSID void *memset(void *s, int ch, size_t n); 函数解释:将 s 中前 n 个字节替换为 ch 并返回 s;strncpy (set.ssid,ssid,sizeof(ssid); /char * strncpy(char *dest, char *src, size_t n);将字符串 src 中最多 n 个字符复制到字符数组 dest 中memset (set.key,
11、0,sizeof(set.key); /更改密码strncpy (set.key,key,sizeof(key); /非常好的可以借鉴的东东NEW#define B2400 0#define B4800 1init_uart(B2400);void init_uart( char Baud ) if(Baud=B2400)TH1 = 0xE8;else if(Baud=B4800)TH1 = 0xF4; NEW关于 extern 说明函数当定义一个函数时,若在函数返回值的类型前加上说明符 extern,则称此函数为外部函数。Extern 说明可以省略,一般的函数都隐含说明为 extern。所以
12、,我们以前所定义的函数都属于外部函数外部函数的特征是:可以被其他编译单位中的函数调用。通常,当函数调用语句与被调用语句不再同一个编译单位,并且函数的返回值为非整数时,应该在调用语句所在函数的说明部分用 extern 对所调用的函数进行函数说明关于用 static 说明函数当定义一个函数时,若在函数返回值的类型前加上说明符 static,则称此函数为静态函数,静态函数的特征是:只限于本编译单位的其他函数调用它,而不允许其他编译单位中的函数对他进行调用。从这个意义上说,静态函数又可称作内部函数(内部于本文件的函数)使用静态函数可以避免不同编译单位因函数同名而引起混乱。若强行调用静态函数,将会产生错
13、误信息。Static 用于函数的定义中static void ENC28J60_SPI2_Init(void)/我认为使用 static 是为了下次不再进入,以提高速度SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );/SPI2 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_G
14、PIOG, ENABLE );/PORTB,D,G 时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; / 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /IO 口速度为 50MHzGPIO_Init(GPIOD, /根据设定参数初始化 GPIOD.2GPIO_SetBits(GPIOD,GPIO_Pin_2); /PD.2 上拉结构体,共用体,和用户定义类型C 语言允许使用 type
15、def 说明一种新的类型名,说明新类型名的语句一般形式为:Typedef int INTEGER;INTEGER m,n; 等价于 int m,n;lTypedef 和指针的结合,如下: Typedef char *CHARP; CHARP p;上面这句等价于 char *p;初学者可能感觉上面的不好理解,下面以更直观的方式来解释1.首先按照通常定义变量的方法写出定义的主体:Char *p; 2.将变量名换成新类型名Char * CHARP ;3.在最左边加上关键字 typedef;Typedef char * CHARP;4.可以用新类型定义变量了CHARP p;给结构体变量,数组赋初值St
16、ruct studentChar name 12;Char sex;Struct data birthday;Float sc4; std=“li ming”,m,1962,5,10,88,76,89.5,90;Const 常量在程序中作为只读变量的前缀,例如 const int i=5; 这样的话在程序后面如果要修改 I 的值的话程序会报错,除非硬件触发会改变 I 的值Sizeof 操作符这个操作符返回的是操作数对应数据类型的字节数,记住是字节数例如在 32 为操作系统中,sizeof (int)返回值为 4 sizeof(char )返回值为 1;sizeof(指针变量)返回值为 4 这个因为指针变量是一个地址,在一个 32 位的系统中一个地址所占的存储空间是 4 个字节,也就是 32 位/我们看一看下面这个经典的东西#define START_TIME time=0;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);TIM_Cmd(TIM2, ENABLE)你会发现在这个宏定义中出现了三个语句,这是允许的,只要最后的一个语句的分号去掉即可