历史上的今天
今天是:2024年08月26日(星期一)
2018年08月26日 | STM32 学习三 GPIO操作
2018-08-26 来源:eefocus
一、基础知识
GPIO寄存器
32位配置寄存器:GPIOx_CRL
32位配置寄存器:GPIOx_CRH
32位数据寄存器:GPIOx_IDR
32位数据寄存器:GPIOx_ODR
32位置位/复位寄存器:GPIOx_BSRR
16位复位寄存器:GPIOx_BRR
32位锁定寄存器:GPIOx_LCKR
工作模式:
输入浮空
输入上拉
输入下拉
模拟输入
开漏输出
推挽式输出
推挽式复用功能
开漏复用功能
每个I/O端口位可以自由编程,而I/O端口寄存器必须按32位字被访问,不允许半字或字节访问。
GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问,这样,在读和更改访问之间产生IRQ时不会发生危险。
每个I/O端口位的基本结构:
端口位配置表:
输出模式位:
端口配置低寄存器CRL:
端口配置高寄存器CRH:
端口输入数据寄存器IDR:
端口输出数据寄存器:ODR
锁定寄存器:GPIOx_LCKR
锁定寄存器位置
端口位设置寄存器:GPIOx_BSRR
端口位复位寄存器:GPIOx_BRR
二、编程测试
在GPIOA.0 .1引脚输出高电平:
#include "stm32f10x_map.h"
int main()
{
//GPIOA->CRL 控制0-7引脚 工作模式
//GPIOA->CRH 控制8-15引脚 工作模式
//1.设置GPIOA引脚工作模式:
//GPIO共16个引脚,让
//GPIOA.0 GPIOA.1
//用推挽式输出、速度50Mhz
GPIOA->CRL=0x33;
//2.在相应的引脚输出一个电平
GPIOA->ODR=0x00; //清零
GPIOA->ODR=0x3; //11
return(1);
}
程序执行结果:
通过第8引脚输入,控制第0引脚输出
#include "stm32f10x_map.h"
int main()
{
//配置 PA.0 推挽输出 50M
// PA.8 输入
GPIOA->CRL = 0x03; //CNF0=00 MODE0=11
GPIOA->CRH = 0x04; //CNF0=01 MODE0=00 //模拟CNF0=00输入时,引脚变化不会引起IDR变化,浮空输入CNF0=01
// PA.0=PA.8
while(1){
if((GPIOA->IDR & 0x0100)==0x0100) //如果第8位为1
GPIOA->ODR = 0x01;
else
GPIOA->ODR = 0x00;
}
return(1);
}
程序仿真结果:
点击8脚,发现0脚跟着改变。
通过高8位控制低8位引脚:方法1
#include "stm32f10x_map.h"
int main()
{
//配置 PA.0-7 推挽输出 50M
// PA.8-15 输入
GPIOA->CRL = 0x33333333; //CNF0=00 MODE0=11
GPIOA->CRH = 0x44444444; //CNF0=01 MODE0=00 //模拟CNF0=00输入时,引脚变化不会引起IDR变化,浮空输入CNF0=01
// PA.0=PA.8...
while(1){
if((GPIOA->IDR & 0x0100)==0x0100) GPIOA->ODR = GPIOA->ODR | 0x01; else GPIOA->ODR = GPIOA->ODR & (~0x01);
if((GPIOA->IDR & 0x0200)==0x0200) GPIOA->ODR = GPIOA->ODR | 0x02; else GPIOA->ODR = GPIOA->ODR & (~0x02);
if((GPIOA->IDR & 0x0400)==0x0400) GPIOA->ODR = GPIOA->ODR | 0x04; else GPIOA->ODR = GPIOA->ODR & (~0x04);
if((GPIOA->IDR & 0x0800)==0x0800) GPIOA->ODR = GPIOA->ODR | 0x08; else GPIOA->ODR = GPIOA->ODR & (~0x08);
if((GPIOA->IDR & 0x1000)==0x1000) GPIOA->ODR = GPIOA->ODR | 0x10; else GPIOA->ODR = GPIOA->ODR & (~0x10);
if((GPIOA->IDR & 0x2000)==0x2000) GPIOA->ODR = GPIOA->ODR | 0x20; else GPIOA->ODR = GPIOA->ODR & (~0x20);
if((GPIOA->IDR & 0x4000)==0x4000) GPIOA->ODR = GPIOA->ODR | 0x40; else GPIOA->ODR = GPIOA->ODR & (~0x40);
if((GPIOA->IDR & 0x8000)==0x8000) GPIOA->ODR = GPIOA->ODR | 0x80; else GPIOA->ODR = GPIOA->ODR & (~0x80);
}
return(1);
}
输出结果:
通过高8位控制低8位引脚:方法2 通过端口位设置/复位寄存器
#include "stm32f10x_map.h"
int main()
{
//配置 PA.0-7 推挽输出 50M
// PA.8-15 输入
GPIOA->CRL = 0x33333333; //CNF0=00 MODE0=11
GPIOA->CRH = 0x44444444; //CNF0=01 MODE0=00 //模拟CNF0=00输入时,引脚变化不会引起IDR变化,浮空输入CNF0=01
// PA.0=PA.8...
while(1){
if((GPIOA->IDR & 0x0100)==0x0100) GPIOA->BSRR = 0x01; //置1
else GPIOA->BRR = 0x01; //清0
if((GPIOA->IDR & 0x0200)==0x0200) GPIOA->BSRR = 0x02; else GPIOA->BRR = 0x02;
if((GPIOA->IDR & 0x0400)==0x0400) GPIOA->BSRR = 0x04; else GPIOA->BRR = 0x04;
if((GPIOA->IDR & 0x0800)==0x0800) GPIOA->BSRR = 0x08; else GPIOA->BRR = 0x08;
if((GPIOA->IDR & 0x1000)==0x1000) GPIOA->BSRR = 0x10; else GPIOA->BRR = 0x10;
if((GPIOA->IDR & 0x2000)==0x2000) GPIOA->BSRR = 0x20; else GPIOA->BRR = 0x20;
if((GPIOA->IDR & 0x4000)==0x4000) GPIOA->BSRR = 0x40; else GPIOA->BRR = 0x40;
if((GPIOA->IDR & 0x8000)==0x8000) GPIOA->BSRR = 0x80; else GPIOA->BRR = 0x80;
}
return(1);
}
通过高8位控制低8位引脚:方法3 定义宏
#include "stm32f10x_map.h"
#define PA0 GPIOA->BRR
#define PA1 GPIOA->BSRR
int main()
{
//配置 PA.0-7 推挽输出 50M
// PA.8-15 输入
GPIOA->CRL = 0x33333333; //CNF0=00 MODE0=11
GPIOA->CRH = 0x44444444; //CNF0=01 MODE0=00 //模拟CNF0=00输入时,引脚变化不会引起IDR变化,浮空输入CNF0=01
// PA.0=PA.8...
while(1){
if((GPIOA->IDR & 0x0100)==0x0100) PA1 = 0x01; else PA0 = 0x01; //清0
if((GPIOA->IDR & 0x0200)==0x0200) PA1 = 0x02; else PA0 = 0x02;
if((GPIOA->IDR & 0x0400)==0x0400) PA1 = 0x04; else PA0 = 0x04;
if((GPIOA->IDR & 0x0800)==0x0800) PA1 = 0x08; else PA0 = 0x08;
if((GPIOA->IDR & 0x1000)==0x1000) PA1 = 0x10; else PA0 = 0x10;
if((GPIOA->IDR & 0x2000)==0x2000) PA1 = 0x20; else PA0 = 0x20;
if((GPIOA->IDR & 0x4000)==0x4000) PA1 = 0x40; else PA0 = 0x40;
if((GPIOA->IDR & 0x8000)==0x8000) PA1 = 0x80; else PA0 = 0x80;
}
return(1);
}
本文学习 《刘凯老师STm32培训视频》,感谢老师辛勤付出。
编程测试:让开发板的LED灯闪烁
同事帮调试成功的代码,感谢同事的协助。
[c] view plain copy
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
void Delay (u32 nCount)
{
for(; nCount != 0; nCount--);
}
void GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
int main(void)
{
SystemInit();
GPIO_Config();
while(1){
GPIO_SetBits(GPIOC , GPIO_Pin_2);
GPIO_SetBits(GPIOC , GPIO_Pin_2);
GPIO_ResetBits(GPIOB , GPIO_Pin_9);
Delay(0xfffff);
Delay(0xfffff);
Delay(0x5ffff);
GPIO_SetBits(GPIOC , GPIO_Pin_3);
GPIO_ResetBits(GPIOC , GPIO_Pin_2);
GPIO_SetBits(GPIOB , GPIO_Pin_9);
Delay(0xfffff);
Delay(0xfffff);
Delay(0x5ffff);
}
}
史海拾趣
|
现在公司准备用c#开发一个项目 运行在wince平台上。 我现在还没搞清楚 这个环境应该怎么搭建。 有没有乐于助人的? 帮帮我这个可怜的人吧。 感谢 万分感谢。 Q:252847391 非诚勿 ...… 查看全部问答> |
|
那位高手用过dp-1581+单片机开发过东西,现在学习中... 那位高手用过dp-1581+单片机开发过东西,现在学习中...能给点代码参考学习一下,那怕最简单的都可以,只是学习用的现在手里有一个仿真板 stc89c52+dp-1581 玩了几天也没玩转,望高手指教一下,学习中...... … 查看全部问答> |
|
我用PB编译好了winCE内核后,已经把镜像下载到了目标平台上,跑起来了。现在下一步是开发应用程序,就是把evc下的应用程序也下载到目标平台上。我不想使用把应用程序编译到内核然后一起下载到目标板上的的方法,觉得那样不够灵活。请问内核下载到目 ...… 查看全部问答> |




