1、不使用库函数的IO口操作Systick 部分内容属于NVIC控制部分,一共有4个寄存器SysTick_CTRL, 0xE000E010 -- 控制寄存器默认值:0x0000 0004SysTick_LOAD, 0xE000E014 -- 重载寄存器默认值:0x0000 0000SysTick_VAL, 0xE000E018 -- 当前值寄存器默认值:0x0000 0000SysTick_CALIB, 0xE000E01C -- 校准值寄存器默认值:0x0002328SysTick_CTRL 寄存器内有4个bit具有意义第0位:ENABLE,Systick 使能位(0:关闭Systick功能;1:开启Systick功能)第1位:TICKINT,Systick 中断使能位(0:关闭Systick中断;1:开启Systick中断)第2位:CLKSOURCE,Systick时钟源选择(0:使用HCLK/8 作为Systick时钟;1:使用HCLK 作为系统时钟)第16位:COUNTFLAG,Systick计数比较标志IO口的位操作实现该部分代码实现对STM32各个IO口的位操作,包括读入和输出。
当然在这些函数调用之前,必须先进行IO口时钟的使能和IO口功能定义。
此部分仅仅对IO口进行输入输出读取和控制。
代码如下:#define BITBAND(addr,bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))#define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))//IO口地址映射#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 55#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08//IO口操作,只对单一的IO口!//确保n的值小于16!#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入以上代码的实现得益于CM3的位带操作,具体的实现比较复杂,请参考<<CM3权威指南>>第五章(87页~92页)。
有了上面的代码,我们就可以像51/A VR一样操作STM32的IO口了。
比如,我要PORTA的第七个IO口输出1,则可以使用PAout(6)=1;既可以实现。
我要判断PORTA的第15个位是否等于1,则可以使用if(PAin(14)==1)…;就可以了。
另种方式:(基本上做出来了)我的STM32板子PA0和PA1接的LED灯,所以先映射这两位。
查看手册中的寄存器组起始地址(原文件名:地址.jpg)引用图片GPIOA是 0x4001 0800GPIOD是0x4001 1400端口输出数据寄存器(GPIOx_ODR) 的偏移地址是 0x0c根据公式:别名区 = ADDRESS=0x4200 0000 + (0x0001 080C*0x20) + (bitx* 4) ;bitx:第x位得到PA.0和PA.1的别名区地址#define PA_Bit0 ((volatile unsigned long *) (0x42210180))#define PA_Bit1 ((volatile unsigned long *) (0x42210184))//42228180#define PD_Bit7 ((volatile unsigned long *) (0x4222819C))#define PD_Bit13 ((volatile unsigned long *) (0x422281CC))#define PD_Bit3 ((volatile unsigned long *) (0x4222818C))#define PD_Bit4 ((volatile unsigned long *) (0x42228190))接下来就可以对PA.0和PA.1进行位操作了*PA_Bit0 = 1; //PA.0 置1*PA_Bit1 = 0; //PA.1 置0还可以读出这一位的值:while(1){*PA_Bit1 =(~*PA_Bit1);Delay(1000); //延时1秒}PA.1接的LED会闪烁。
由于对STM32的存储结构不了解,0x4200 0000不知道是从哪里来的。
后来看到了一个PDF文档(原文件名:存储.jpg)引用图片原来0x4200 0000是外设别名区域的地址。
我也是刚刚学习STM32,有错误的地方请大家指点。
3、使用库函数,如下部分程序对IO的操作。
while(1){/* Turn on LD1 */GPIO_SetBits(GPIOD, GPIO_Pin_8);/* Insert delay */Delay(0xAFFFF);/* Turn on LD2 and LD3 */GPIO_SetBits(GPIOD, GPIO_Pin_9 | GPIO_Pin_10);/* Turn off LD1 */GPIO_ResetBits(GPIOD, GPIO_Pin_8);/* Insert delay */Delay(0xAFFFF);/* Turn on LD4 */GPIO_SetBits(GPIOD, GPIO_Pin_11);/* Turn off LD2 and LD3 */GPIO_ResetBits(GPIOD, GPIO_Pin_10 | GPIO_Pin_9);/* Insert delay */Delay(0xAFFFF);/* Turn off LD4 */GPIO_ResetBits(GPIOD, GPIO_Pin_11);}4、IO1PIN=(IO1PIN&0xff00ffff)|((Reg_Code&0xff)<<16);//将要写的数据先赋给单片机的16~23脚5、最小系统板上可以使用的普通IO口:A 0-150-10、12、13可作为一般的IO口使用,由于有第二功能,11、14、15管脚在普通IO口时会有不正常现象(比如设置成高电平输出时14电压几乎为0;设置成带上拉输入时11电压也很小(0.9左右),14电压几乎为0),在使用时应避免使用这些口B 0-15C 0-15D 0 1 2EFG6、IO口模式①模拟输入模式(GPIO_Mode_AIN)PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7,PB0,PB1,PC0, PC1, PC2,PC3,PC4,PC5可以设置成该模式,即这16个口可以用作AD输入②输入浮空模式(GPIO_Mode_IN_FLOATING)UART的输入引脚设置成该模式③带下拉输入(GPIO_Mode_IPD)④带上拉输入(GPIO_Mode_IPU)⑤开漏输出(GPIO_Mode_Out_OD)输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内).要实现线与需要用OC(open collector)门电路.是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小,效率高。
输出既可以向负载灌电流,也可以从负载抽取电流。