精华内容
下载资源
问答
  • io口分类
    2021-04-29 19:19:54

    “呼吸灯”其实就是小灯的亮度是逐渐变化的,也就是说,只要能够使用单片机控制小灯的亮度,“呼吸灯”的效果也就实现了。

    使用C语言控制单片机IO交替输出高低电平,实现LED小灯的闪烁效果。核心代码如下:

    while(1){
            P20 = 0;
            delay(10);
            P20 = 1;
            delay(10);
        }
    

    IO输出的高低电平持续时间都是10个单位,一个完整的周期内,LED小灯的亮灭时间都是相等的。由此可见,使用单片机控制小灯亮度,就是控制一个周期内,LED小灯的亮灭持续时间长短而已。代码如下:

    
    /* IO模拟呼吸灯*/
    #include "gd32f30x.h"
    #include "gd32f303c_eval.h"
    #include "systick.h"
    
    void delay(uint32_t i);
    
    void delay(unsigned int n) {
        char darkTime = 0, dir = 1;
        unsigned int cnt = 0;
         unsigned int x ;
    	   while(n--) {
    	    x=50;
           while(x--);			 		 
    	}
    }
    
    void twinkle_once(unsigned char darkTime) {
          gd_eval_led_off(LED2);
    	    delay(100-darkTime);
    	    gd_eval_led_on(LED2);
    	     delay(darkTime);
    
    }
    int main(void)
    {  
       char darkTime = 0, dir = 1;
        unsigned int cnt = 0;
        gd_eval_led_init(LED2);
        
        while(1){
    
            cnt ++;
            twinkle_once(darkTime);
            if(cnt == 50){
                cnt = 0;
                if(dir)
                    darkTime += 1;
                else
                    darkTime -= 1;
    
                if(darkTime >= 100)
                    dir = 0;
                if(darkTime <= 60)
                    dir = 1;
            }
        }
    }
      
    
    

    通过按键控制呼吸频率代码如下:

    
    
    /*
        Copyright (C) 2017 GigaDevice
    
        2017-06-23, V1.0.0, demo for GD32F30x
    */
    
    /* IO模拟呼吸灯*/
    #include "gd32f30x.h"
    #include "gd32f303c_eval.h"
    #include "systick.h"
    
    uint16_t darkTime = 0, dir = 1;
    unsigned int cnt = 0;
    uint32_t temp;
    
    
    void delay(unsigned int n) {
         unsigned int x ;
    	   while(n--) {
    	    x=50;
           while(x--);			 		 
    	}
    }
    /*闪烁次数*/
    void twinkle_once(unsigned char darkTime) {
          gd_eval_led_off(LED2);
    	    delay(100-darkTime);
    	    gd_eval_led_on(LED2);
    	     delay(darkTime);
    
    }
    int main(void)
    {  
        gd_eval_led_init(LED2);
    	 gd_eval_led_init(LED3);
    	   
    
    	gd_eval_key_init(KEY_WAKEUP,KEY_MODE_GPIO);
    	gd_eval_key_init(KEY_TAMPER,KEY_MODE_GPIO);
        systick_config();
        
        while(1){
    				if(RESET == gd_eval_key_state_get(KEY_WAKEUP)){
                /* delay 50ms for software removing jitter */
                delay_1ms(50);
                if(RESET == gd_eval_key_state_get(KEY_WAKEUP)){				 
        while(1){
    
            cnt ++;
            twinkle_once(darkTime);
            if(cnt == 50){
                cnt = 0;
                if(dir)
                    darkTime += 8;
                else
                    darkTime -= 8;
    
                if(darkTime >= 100)
                    dir = 0;
                if(darkTime <= 60)
                    dir = 1;
            }
      }
    }
    }
    }
    }
    
    更多相关内容
  • 随着智能时代的到来,各种人工智能应用的产品如:车载导航系统、可穿带设备、智能家居等目不暇接,而在这中间,微控制器的应用范围越来越广泛。... IO口分为GPIO口和专用IO口。 GPIO的八种工作模式详解:浮
  • 51单片机——IO口

    2022-08-31 16:03:54
    IO口分类 此单片机有39个IO口,P0到P3每个8个口,P4有7个口 一般用P1,P2,P3,P4口与外部模块通信,这4个口是准双向口,具备弱上拉电阻的;P0口重新上电后是开漏输出,若总线扩展用,不需要加上拉电阻,但是作为IO...

    IO口分类

    此单片机有39个IO口,P0到P3每个8个口,P4有7个口

    一般用P1,P2,P3,P4口与外部模块通信,这4个口是准双向口,具备弱上拉电阻的;P0口重新上电后是开漏输出,若总线扩展用,不需要加上拉电阻,但是作为IO口与外部模块通信的时候,要加上拉电阻。

    P4口是新版本51单片机添加的,在传统的51头文件里面没有关于P4的配置,需要自己添加,对于P4口的首地址是E8H,有7个口所以增添头文件如下

    sfr  P4  = 0xe8;    /*C语言中声明P4口特殊功能寄存器地址*/
    sbit P40 = 0xe8; /*C语言中声明P4.0口位地址*/
    sbit P41 = 0xe9; /*C语言中声明P4.1口位地址*/
    sbit P42 = 0xea;
    sbit P43 = 0xeb;
    sbit P44 = 0xec;
    sbit P45 = 0xed;
    sbit P46 = 0xee;
    

    单片机控制IO口

    单片机自身会引出IO口,这些IO口如果和一些片外外设相连,单片机就可以通过IO口和片外外设信息交流

    而在单片机中,CPU对各种片内外设的控制是采用特殊功能寄存器(SFR)的集中控制方式共有26个特殊功能寄存器,这些寄存器是对各种片内外设的控制寄存器和状态寄存器,地址映射在RAM区的80H到FFH内,所以CPU要对单片机的片内外设或者片外外设操作,都需要通过寄存器。CPU操作寄存器,从而引起片内外设或者片外外设工作,类似于人类大脑先在相应控制区域产生指令,然后通过神经,控制对应身体部位产生行动

    比如26个特殊功能寄存器中的IO口寄存器是和具体的IO口引脚映射的,那么这些寄存器就可以控制这些IO口,而且这些寄存器会被标识符命名,比如(srf P0= 0x80,0x80这个地址就是控制P0串口的寄存器地址,通过操作P0变量,就可以控制P0串口)。单片机直接对这些寄存器地址内容修改或者检测,会直接影响到具体IO口硬件的电平,IO口是可以寻址的,IO口组的各个口相当于可寻址空间的一个位,在相关头文件里面,会对这些地址进行配置

    注意:对于可以位寻址的SFR,其字节地址的末位只能是0H或8H

    有两个指令配置寻址,sfr和sbit

    IO口的高低电平相当于就是对IO口与模块或者单片机连接的开关,如果低电平就导通,高电平就截止

    注意:sfr和sbit指令是非标准C语言指令,不在ANSI标准中,一般的C编译器可能不认识这两个指令

    sfr

    通过sfr指令将单片机里的特殊功能寄存器取一个名字;操作此变量,就会引起对应寄存器的存储的值变化

    sbit

    再通过sbit指令将IO口组的具体某个口对应的内存地址映射到某个变量

    代码实例

    #include "reg52.h"
    
    sbit led1 = P3^7;  
    sbit led2 = P3^6;
    void main(){
       while(1){
    		 led1=0;
             led1=1;
    		 led2=0;
    		 led2=1;
    	 }
    	 
    }

    我们在操作的时候对配置的变量操作,就会操作单片机的某个内存地址的内容,而这个内存地址又会影响到到具体IO口的硬件电平,这样操作此变量就相当于操作此IO口,通过给变量赋值0,1从而控制IO口电平的高低

    由于看原理图,P3^7代表的是P3IO口的7引脚,而P3IO口的7引脚又和一个小灯连接着,通过sbit将led1指向P3IO口的7引脚,然后给led1赋值0,就相当于给该IO口引脚传递低电平,,相当于GND,传递低电平后,灯和IO口和电源形成成回路,从而让灯亮

    输入与输出

    输入与输出都是针对单片机自身来说的,即输入给单片机,和单片机输出

    而且对于52单片机,输入输出功能不需要配置

    输入

    对于单片机,输入就是将外部模块的内容传递给单片机,在代码里面,如果将已经有值的IO口,赋值给一个变量,对于单片机就是输入,因为可能外部模块与这个IO口连通了的,运行之后,外部模块对IO口产生了数据,然后单片机用一个变量接受IO口的数据,就可以通过这个数据来操作其他的模块

    输出

    对于单片机,输出就是将单片机的内容传递给外部模块,在代码里面,如果将具体的值,0或1等,赋值给某个IO口,对于单片机就是输出,因为这个IO口所赋的值会影响与这个IO口连接的外部模块

    代码实例

    #include "reg52.h"
    
    sbit led1 = P3^7;  
    sbit IFfire=P1^0;
    void main(){
       while(1){
    		 led1=1;
             int input=IFfire;
             if(input==0){
                 led1=0;      
             }     
    		 
    	 }
    	 
    }

    首先将led1配置为1,对于单片机这个口就是输出,单片机通过将P3^7口配置为高电平,导致与该口所连的灯不亮,然后用input接受火焰传感器传给P1^0口的数据,对于单片机这个口就是输入,如果该口是低电平,那么让led1配置为1,让灯亮

    小项目

    一、项目1-灯的闪烁

    #include "reg52.h"
    
    sbit ledblue =P3^7;
    sbit ledyellow =P3^6;
    void delay500(){
     int n=61404;
     while(n--);
    }
    void light(int x,int y){
     ledblue=x;
     ledyellow=y;
    
    }
    void main(){
       while(1){
       light(0,0);
    	 delay500();
       light(1,1);
    	 delay500();
       light(0,1);
    	 delay500();
       light(1,1);
    	 delay500();
       light(0,0);
    	 delay500();
       light(1,1);
    	 delay500();
       light(1,0);
    	 delay500();
       light(1,1);
    	 delay500();
       
    	 }
    
    }

    要实现灯的闪烁,需要延时函数,51单片机可以自动帮助生成延迟函数的代码(比如延迟0.5秒,相当于数61404次数)

    二、项目2-按键控制灯

    #include "reg52.h"
    #define LightBlue 1
    #define LightYellow 2
    #define LightAll 3
    sbit ledblue =P3^7;
    sbit ledyellow =P3^6;
    sbit key1=P2^1;
    sbit key2=P2^0;
    
    void delay100(){
    	int tmp=61404*0.2;
    	while(tmp--);
    }
    void delay500(){
    	int tmp=61404;
    	while(tmp--);
    }
    int light(int x){
        if(x==LightBlue){
    		 int n=3;
         while(n--){
          ledblue=0;
          delay500();
    	    ledblue=1;
    	    if(n!=0)
    	    delay500();
    	   }
    	  }
    	 if(x==LightYellow){
    		 int n=3;
    	 	 while(n--){
          ledyellow=0;
          delay500();
    	    ledyellow=1;
    	    if(n!=0)
    	    delay500();
    	   }
        }
       if(x==LightAll){
    		 int n=3;
    		 while(n--){
          ledyellow=0;
    	    ledblue=0;
          delay500();
    	    ledyellow=1;
    	    ledblue=1;
    	    if(n!=0)			
    	    delay500();
    	   }
        }
        return x;		
    }	
    void main(){
    	int flag=LightAll; 
    	int tmp=LightAll;
    	while(1){
    		 int n=3;
    		ledblue=1;
    		ledyellow=1;
    		if(key1==0){
               delay100();
               if(key1==0){
    			if(tmp==LightAll){
    				flag=LightBlue;
    				tmp=light(flag);
    				continue;
           }
    			if(tmp==LightBlue){
    				flag=LightYellow;
    				tmp=light(flag);
    				continue;
           }
    			if(tmp==LightYellow){
    				flag=LightAll;
    				tmp=light(flag);
    				continue;
           }
        }
       }
      }
    }

    单片机点灯和物理点灯的区别

    现实中,按键控制点灯,按键和灯在一个电路中,按键相当于开关,控制电路的通断而实现灯的亮灭

    在单片机中,按键是一个电路,可以输出高低电平;点灯是一个电路,需要高低电平,而单片机是一个媒介,去检测按键的输出的高低电平,然后对应给灯输入高低电平,在逻辑上形成按键控制点灯

    消抖

    消抖,因为人按键按下到弹起可能有个150ms,如果板子用久了接触不良可能抖动导致按下按键,这样抖动从按下到弹起速度很快。软件消抖就是不立刻检测,延迟检测,延迟时间大于抖动的时间小于按键到松开的时间,那么就可以避免抖动,记录下的都是人为的信号

    记录状态位

    当按键需要控制的模块较多时,可以用一个状态变量来记录状态,模块可根据对应状态变量的值实现相应的功能,如果需要记录上一次的状态,可以再增加一个变量来记录上一层的状态

    io口电平翻转

    如果想要一个按键实现按下点灯,再次按下关灯,就可以通过led=!led,来翻转io的电平,也相当于是一个记录状态位的操作

    三、终项目-简易电动车报警器

    #include "reg52.h"
    
    sbit kaiguan  =P2^3;
    sbit zhendong =P3^3;
    sbit key1     =P2^1;
    sbit key2     =P2^0;
    sbit A        =P1^5;
    sbit C        =P1^7;
    sbit led1     =P3^7;
    sbit led2     =P3^6;
         
    
    void delay200(){
    	int tmp=61404*0.3;
    	while(tmp--);
    }
    void delay400(){
    	int tmp=61404*0.6;
    	while(tmp--);
    }
    
    void main(){
    	led1=1;
    	led2=1;
     while(1){
    	 if(A==1){
    		 led1=1;
    		 led2=1;
    		 kaiguan=0;
    		 delay200();
    		 kaiguan=1;
    		 delay200();
    		 kaiguan=0;
    		 delay400();
    		 kaiguan=1;
    	 }
     
    	 if(C==1){
    		 led2=0;
    		 led1=0;
    		 kaiguan=0;
    		 delay200();
    		 kaiguan=1;
    	 }
      if(led2==0&&led1==0&&zhendong==0){
    		int i=0;
    		for(i;i<3;i++){
    		int n=3;
    		while(n--){
          kaiguan=0;
          delay200();
    		  kaiguan=1;
    			delay200();
    		}
    	}
     }
    
    }
    }
     
    
    
    

    用到的模块

    振动传感器

    VCC和GND针脚供电,DO口可以接到单片机的IO口,如果振动传感器感受到了振动,DO口就会向IO口发送低电平,并且DO-LED灯会亮,没有振动DO口维持高电平

    振动传感器用于检测振动

    继电器

    继电器相当于是一个电路控制的开关,可以控制家用220v电灯的那种开关,继电器VCC和GND口连单片机供电,IN口连接单片机的IO口,当单片机向IN口输入低电平时,继电器另一端COM口和NO口接通,相当于开关闭合,就可以维持电路导通;默认情况,当继电器线圈两端无电压或电压不够,COM口和NC口接通,相当于开关断开。

    继电器用于给喇叭当开关

    433m射频遥控模块

    该模块配套了一个433射频遥控器,模块的VCC和GND口连单片机供电,D0,D1,D2,D3连接单片机IO口

    433射频遥控器的ABCD按键分别对应D0到D3口,按下按键,会给模块发出信号,对应的D口就会给单片机的对应IO口发送高电平

    遥控模块用于整体的开关,按下A键关闭报警器,按下C键打开报警器

    小喇叭

    小喇叭和继电器和电池,组成报警模块,如果简易报警器处于打开状态,振动模块感应到振动就会,打开继电器,从而报警;如果简易报警器处于关闭状态,继电器是关闭的,振动模块就算感应到振动也不会报警

    展开全文
  • 行业分类-设备装置-单IO口同时实现输入输出功能的装置及其实现方法.zip
  • 行业分类-电子-IO口扩展电路的说明分析.rar
  • 目录 一、IO口的八种模式 二、IO口的配置 三、外部中断配置 四、串口配置 五、定时器配置 六、项目 一、IO口的八种模式 输入 浮空输入:浮空,顾名思义,就相当与此端口在默认情况下什么都不接,呈高阻态,这种设置...

    目录

    一、IO口的八种模式

    二、IO口的配置

    三、外部中断配置

    四、串口配置

    五、定时器配置

    六、项目


    一、IO口的八种模式

    输入

    浮空输入:浮空,顾名思义,就相当与此端口在默认情况下什么都不接,呈高阻态,这种设置在数据传输时用的比较多。

    上拉输入:即通过一个上拉电阻,使它接到vcc

    下拉输入:即通过一个下拉电阻,使它接到gnd

    模拟输入:一般用于adc数模转换

    输出

    推挽输出:既可以输出高电平,也可以输出低电平

    复用推挽输出:一般是一些复用端口再用,比如uart、iic等

    开漏输出::输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内).

    复用开漏输出 :一般用于内外设功能(TX1,MOSI,MISO.SCK.SS)

    二、IO口的配置

    1. 时钟使能

    2. 配置GPIO

    3. 初始化GPIO

    此图片用于M3内核 

    d7ba40a19ab145038a248de6a285f2f7.png

    /*-------led-------*/
    
    #include "led.h"
    
    void led_Init(void)
    {
    	GPIO_InitTypeDef led;
    	
    	//1.时钟使能
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC ,  ENABLE);
    	
    	//2.配置GPIO
    	
    		led.GPIO_Mode = GPIO_Mode_Out_PP ;
    		led.GPIO_Pin  = GPIO_Pin_13;
    		led.GPIO_Speed = GPIO_Speed_50MHz;
    	
    	//3.初始化GPIO
    	
    	 GPIO_Init(GPIOC,  &led);
    }
    
    /*-------shake-------*/
    
    #include "shake.h"
    
    void shake_Init()
    {
    		GPIO_InitTypeDef shake;
    
    	
    	//1.使能时钟
    	
    		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,  ENABLE);
    	
    	//2.配置GPIO
    	
    	shake.GPIO_Mode = GPIO_Mode_IPD;
     	shake.GPIO_Pin  =   GPIO_Pin_4;
    	shake.GPIO_Speed = GPIO_Speed_10MHz;
    	
    	//3.初始化GPIO
    	
    		GPIO_Init(GPIOA,  &shake);
    	
    }
    
    /*-------relay-------*/
    
    #include "relay.h"
    
    void relay_Init()
    {
    	GPIO_InitTypeDef relay;
    	
    	//1.使能时钟
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,  ENABLE);
    
    	
    	//2.配置GPIO
    	
    	relay.GPIO_Mode = GPIO_Mode_Out_PP;
    	relay.GPIO_Pin  = GPIO_Pin_3;
    	relay.GPIO_Speed = GPIO_Speed_10MHz;
    	
    	//3.初始化GPIO
    
    	GPIO_Init(GPIOA,  &relay);
    		
    
    }
    
    /*-------delay-------*/
    
    #include "delay.h"
    
    
    //us
    
    void delay_us(int delay_us)
    {    
      volatile unsigned int num;
      volatile unsigned int t;
     
      
      for (num = 0; num < delay_us; num++)
      {
        t = 11;
        while (t != 0)
        {
          t--;
        }
      }
    }
    
    //ms
    void delay_ms( int delay_ms)
    {    
      volatile unsigned int num;
      for (num = 0; num < delay_ms; num++)
      {
        delay_us(1000);
      }
    
    }

    三、外部中断配置

    1. 配置GPIO并使能时钟

    2. 把GPIO映射到对应的中断线

    3. 配置外部中断

    4. 配置NVIC组

    5. 配置NVIC中断控制器

    6. 配置中断服务函数

    #include "exit.h"
    #include "shake.h"
    
    void exit_Init()
    {
    	EXTI_InitTypeDef exti;
    	NVIC_InitTypeDef nvic;
    	
    	//1.配置GPIO
    	
    	shake_Init();
    	
    	RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO,  ENABLE); //打开中断用到的时钟
    	GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource4 ); //把GPIO映射到对应的中断线---->在GPIO.H
      NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2); //配置NVIC优先级组--->在misc.h
    
    
    	
    	//2.配置外部中断
    	
    	exti.EXTI_Line      = EXTI_Line4;
    	exti.EXTI_Mode      = EXTI_Mode_Interrupt;
    	exti.EXTI_Trigger   = EXTI_Trigger_Falling;
    	exti.EXTI_LineCmd = ENABLE;   
    	
    	//3.初始化外部中断
    	
      EXTI_Init(&exti);
    
    	//4.配置NVIC中断控制器
    	
    	nvic.NVIC_IRQChannel     = EXTI4_IRQn; //中断源---->在misc.c--->stm32f10x.h           
    	nvic.NVIC_IRQChannelPreemptionPriority  = 1;
    	nvic.NVIC_IRQChannelSubPriority    = 1;
    	nvic.NVIC_IRQChannelCmd  = ENABLE;
    	
    	//5.初始化NVIC
    	
      NVIC_Init(&nvic);
    
    	//6.配置中断服务函数  ----> 在启动文件----用的那个中断源就用那个中断服务函数
    }

    四、串口配置 

    1. 配置GPIO并使能对应时钟

    2. 配置串口

    3. 配置串口中断

    4. 配置NVIC中断控制器

    5. 配置中断服务函数

    #include "uart.h"
    #include "stdio.h"
    
    typedef struct __FILE FILE;
    
    void uart_Init()
    {
    	GPIO_InitTypeDef txrx;
    	USART_InitTypeDef uart;
    	NVIC_InitTypeDef nvic;
    
    	
    	//1.GPIO配置并使能时钟
    
    	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,  ENABLE); 
    	RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1,  ENABLE); 
    	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2); //配置NVIC优先级组--->在misc.h
    
    	
    	txrx.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出,因为txrx是复用端口
    	txrx.GPIO_Pin  = GPIO_Pin_9;
    	txrx.GPIO_Speed = GPIO_Speed_50MHz;
    	
    	GPIO_Init(GPIOA,  &txrx); //初始化TX
    
    	txrx.GPIO_Mode = GPIO_Mode_IN_FLOATING; //因为是接受,所以输入用浮空
    	txrx.GPIO_Pin  = GPIO_Pin_10;
    	//txrx.GPIO_Speed = GPIO_Speed_50MHz; //要不要都一样,因为速度是输出才用
    	
    	GPIO_Init(GPIOA,  &txrx); //初始化RX
    
    	
    	//2.配置串口
    	
    	uart.USART_BaudRate = 9600;
    	uart.USART_WordLength  = USART_WordLength_8b;
    	uart.USART_StopBits = USART_StopBits_1;
    	uart.USART_Parity = USART_Parity_No;
    	uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    	uart.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
      
    	 USART_Cmd(USART1,ENABLE  ); //使能串口
    
    	//3.初始化串口
    	
    	 USART_Init(USART1, &uart);
    
    	//4.设置串口中断类型
    
    	 USART_ITConfig(USART1, USART_IT_RXNE ,  ENABLE); //接收中断
    
    
    	//5.配置NVIC
    	
    	nvic.NVIC_IRQChannel     = USART1_IRQn; //中断源---->在misc.c--->stm32f10x.h           
    	nvic.NVIC_IRQChannelPreemptionPriority  = 1;
    	nvic.NVIC_IRQChannelSubPriority    = 1;
    	nvic.NVIC_IRQChannelCmd  = ENABLE;
    		
         NVIC_Init(&nvic);
    		
    	
    }
    
    
    void sendBits(USART_TypeDef* USARTx, uint16_t Data) //发送一个字符
    {
    	
    		 USART_SendData( USARTx,  Data);
    		 while( USART_GetFlagStatus(USART1, USART_FLAG_TXE )!= SET); 
    	
    }
    
    void sendStr(USART_TypeDef* USARTx, char *Data) //发送一个字符串
    {
    	while(*Data != '\0')
    	{
    		sendBits(USARTx,*Data);
    		Data++;
    		
    	}
    }
    	
    
    int fputc(int ch , FILE * p) //printf重定向----<把打印到显示屏的数据,改成打印到串口>
    {
    		USART_SendData( USART1,  ch);
    		 while( USART_GetFlagStatus(USART1, USART_FLAG_TXE )!= SET);		
    	
    	
    	return ch;
    	
    }
    	
    void USART1_IRQHandler() //6.中断服务函数
    {
    	char buf;
    	
    	if( ( USART_GetITStatus(USART1,  USART_IT_RXNE)) == SET) //等于SET就说明已经产生一个中断标志位
    	{
    		buf =  USART_ReceiveData( USART1);
    
    	if(buf == 'o')
    	{
    		sendStr(USART1, "ok");
    		printf("666"); //---<因为printf本身就可以携带字符串,所以执行fputc,是一位一位给SendData发送的>
    		
    		//while( USART_GetFlagStatus(USART1, USART_FLAG_TXE )!= SET); //USART_FLAG_TXE是发送完成标志,== 0,说明发送完成
    	}
    
    	}
    	
    	 USART_ClearFlag( USART1,USART_FLAG_TXE  );//清除中断标志
    }

    printf重定义 

    就是把fputc这个函数原本打印到显示器的数据,给它改到串口

    五、定时器

    1. 定时器配置并使能时钟

    2. 配置定时器中断 (T=(重装值)*(预分频系数)/72Mhz)

    3. 配置NVIC中断控制器

    4. 编写中断服务函数

    时钟树 

    ba0af313096f4bb683caddc001ece9e9.png

    #include "time.h"
    #include "uart.h"
    
    void time_Init()
    {
    	
    	TIM_TimeBaseInitTypeDef time;
    	NVIC_InitTypeDef nvic;
      RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2,ENABLE  );
      NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2);
    
    	 
    	//1.定时器配置
    		
    	time.TIM_Prescaler  = 7200-1; //预分频系数
    	time.TIM_Period     = 10000-1; //自动重装
    	time.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频,设置定时器时钟CK_INT频率与数字滤波采样
    	time.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
    	
    	//2.定时器初始化并使能
    	
      TIM_TimeBaseInit( TIM2, &time);
    	TIM_Cmd(TIM2,  ENABLE);
    	
    	//3.配置定时器中断
    	
    	 TIM_ITConfig( TIM2,  TIM_IT_Update,  ENABLE);
    
    
    	//4.配置NVIC中断控制器
    	
    	nvic.NVIC_IRQChannel     = TIM2_IRQn; //中断源---->在misc.c--->stm32f10x.h           
    	nvic.NVIC_IRQChannelPreemptionPriority  = 1;
    	nvic.NVIC_IRQChannelSubPriority    = 1;
    	nvic.NVIC_IRQChannelCmd  = ENABLE;
    	
      NVIC_Init(&nvic);
    	
    	
    }
    
    	//5.中断服务函数
    
    void TIM2_IRQHandler()
    {
    	 
    	
    	if(TIM_GetITStatus( TIM2, TIM_IT_Update ) == SET)
    	 {
    		 
    		  TIM_ClearITPendingBit( TIM2, TIM_IT_Update );//清除定时器中断标志位
    		
    			
    					USART_SendData( USART1,  'a');
    					while( USART_GetFlagStatus(USART1, USART_FLAG_TXE )!= SET);
    			
    	 }
    	 
    
    
    }

    systick定时器

    1. 配置时钟源(可以72mhz/9mhz)

    2. 配置重装值 

    3. 向下递减到0触发中断退出定时器

    4. 关闭定时器

    #include "systick.h"
    
    void Delay_ms(int ms) //最大24位
    {
    	int i;
    	SysTick_Config(72000);
    	
    	for(i = 0; i < ms;i++ )
    	{
    		while(!(SysTick->CTRL)& 1<<16 );
    		
    	}
    	
    		SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
    	
    }
    
    void Delay_us(int us) //最大24位
    {
    	int i;
    	SysTick_Config(72);//重装定时器值,t = 重装值*(1/72mhz),反过来讲7200就是,72000*(1/72MHz)=1/1000=1(ms)
    	 
    	for(i = 0; i < us;i++ )
    	{
    		while(!(SysTick->CTRL)& 1<<16 );//如果数到了0,则该为为1
    		
    	}
    	
    		SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 置0
    	
    }

    PWM模式

    1 .使能时钟和使能AFIO时钟(因为需要引脚复用)

    2. 调用函数进行引脚映射

    3. GPIO配置 (这里我们用的定时器3通道2)

    4. 定时器配置

    5. pwm配置

    6. pwm初始化,并使能pwm和使能rcc

     d421918434584778abe9530e3a1a30c8.jpeg

     ea1f60ffa25e4b018097b81c6b7d540e.png

    #include "pwm.h"
    
    void pwm_Init()
    {
    	GPIO_InitTypeDef dj;
    	TIM_TimeBaseInitTypeDef time;
    	TIM_OCInitTypeDef pwm;
    
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,  ENABLE); //用于映射到这个引脚,打开这个引脚的时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,  ENABLE); //引脚复用,必须打开这个时钟
    	RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3,ENABLE  ); //使能定时器3的时钟
    	
      GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 , ENABLE ); //指定管脚映射
    
    	//1.GPIO配置
    	
    	dj.GPIO_Mode = GPIO_Mode_AF_PP;
    	dj.GPIO_Pin  = GPIO_Pin_5;        //*****用的定时器3通道2******
    	dj.GPIO_Speed = GPIO_Speed_50MHz;
    	
    	GPIO_Init( GPIOB, &dj);
    	
    	//2.定时器配置
    	
    	time.TIM_Prescaler  = 7200-1; //自动重装
    	time.TIM_Period     = 200-1; //预分频系数
    	time.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频,设置定时器时钟CK_INT频率与数字滤波采样
    	time.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
    
      TIM_TimeBaseInit( TIM3, &time);
    	
    	//3.PWM配置
    	
    	pwm.TIM_OCMode = TIM_OCMode_PWM1;  //选择pwm1模式,如果定时器向上计数,一旦cnt<crr时,通道为有效电平,定时器向下则无效电平,pwm2则相反
    	pwm.TIM_OutputState = TIM_OutputState_Enable; //使能比较输出,就是打开把输出的电平给到重映射的引脚上
    	pwm.TIM_OCPolarity = TIM_OCPolarity_Low; //选择有效电平为低电平
    	
    	//4.pwm初始化并使能ccr并使能定时器3
    	
    	 TIM_OC2Init( TIM3, &pwm );
    	 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
    	 TIM_Cmd(TIM3,  ENABLE);
    
    	 
    	
    }
    
    
    #include "stm32f10x.h"
    #include "delay.h"
    #include "pwm.h"
    
    int main()
    {
    
    	 pwm_Init();
    		
    	 TIM_SetCompare2(TIM3,  195); //设置比较值
    	
    		while(1)
    		{
    			 delay_ms(1000);
    			 TIM_SetCompare2(TIM3,  175); //设置比较值,180°
    			 delay_ms(1000);
    			 TIM_SetCompare2(TIM3,  195); //设置比较值,0°
    			 			 
    
    
    		
    		
    		} 
    
    }

    DMA(直接寄存器访问)

    DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输

    我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,那我们可不可以减轻消耗cpu的资源呢?

    有,我们可以直接让内存->外设、外设->内存,内存->内存,因为有dma,它不需要经过cpu,可以直接访问flash或SRAM。

    f4cc9457be094549b6c7a5aad28cd230.png 83a953cdf89243449c33be1468715717.png

    40753888afd14a4d80dc7b63aa5563b4.png

    1. 配置DMA

    2. 初始化/使能DMA

    3. 使能串口DMA(这里用的内存->串口)

    4. 获取DMA标志位、判断是否发送完成

    /*
    	
    		内存->外设
    
    */
    
    #include "dma.h"
    
    void dma_Init(DMA_Channel_TypeDef* DMAy_Channelx,u32 *paddr,u32 *maddr,u16 size)
    {
    		DMA_InitTypeDef dma;
    		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,  ENABLE);
    		
    		//1.配置dma
    		
    		dma.DMA_PeripheralBaseAddr = (u32)paddr; //外设地址,是u32位,所以要强转
    		dma.DMA_MemoryBaseAddr = (u32)maddr; //内存地址,是u32位
    		dma.DMA_DIR = DMA_DIR_PeripheralDST; //传输方向,我们选择从内存到外设
    		dma.DMA_BufferSize = size; //设置一次传输的大小,最大传输65536
    	    dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置传输数据外设地址是否递增
    		dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置传输数据内存地址是否递增
    		dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设的数据长度为多少字节传输
    		dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //设置内存的数据长度为多少地址传输 
    		dma.DMA_Mode = DMA_Mode_Normal; //设置模式,是循环发送,还是只发送一次
    		dma.DMA_Priority = DMA_Priority_High; //设置dma的通道优先级,一共有低、中、高、很高4个优先级
    		dma.DMA_M2M = DMA_M2M_Disable; //这是设置内存到内存的使能
    	
    		//2.初始化dma
    	
    		 DMA_Init(DMAy_Channelx , &dma); //用参数传递通道,提高使用性
    
    }
    
    
    void dma_Enable(DMA_Channel_TypeDef* DMAy_Channelx,uint16_t size)
    {
    	 DMA_Cmd(DMAy_Channelx,  DISABLE); //先失能
    	 DMA_SetCurrDataCounter( DMAy_Channelx,  size); //设置数据传输量
    	 DMA_Cmd(DMAy_Channelx,  ENABLE);  //使能
    
    }
    
    #include "stm32f10x.h"
    #include "delay.h"
    #include "dma.h"
    #include "uart.h"
    
    #define SIZE 2000
    
    u8 maddr[SIZE]; //定义maddr
    
    void maddr_Init(u8 * p)
    {
    	int i = 0;
    	for(i = 0; i < SIZE;++i)
    	{
    		*p = '5';
    		 p++;
    	}
    }
    
    int main()
    {
    	 uart_Init();
    	 dma_Init( DMA1_Channel4,(u32 *)&USART1->DR, (u32 *)maddr, SIZE); //初始化dma---USART1->DR---(串口的数据寄存器,也就是这里的外设地址)
    		
    	 maddr_Init(maddr); //给内存地址写值
    	 USART_DMACmd( USART1,  USART_DMAReq_Tx,  ENABLE); //使能外设,并配置成发送
    	 dma_Enable(DMA1_Channel4, SIZE); //使能dma1通道
    	
    	while(1)
    	{
    			 if(DMA_GetFlagStatus( DMA1_FLAG_TC4) == SET) //判断是否发送完成
    			 {
    				  DMA_ClearFlag( DMA1_FLAG_TC4); //发送完成清除标志
    				 
    					break; //打破while,只执行一次
    
    			 }
    
    	}
    		
    
    }

    展开全文
  • 八种IO口模式STM32有八种IO口模式,分别是:模拟输入、浮空输入、上拉输入、下拉输入、开漏输出、推挽输出、复用开漏输出和复用推挽输出。 1、模拟输入GPIO_Mode_AIN模拟输入,即关闭施密特触发器,将电压信号传送到...

    八种IO口模式

    STM32有八种IO口模式,分别是:模拟输入、浮空输入、上拉输入、下拉输入、开漏输出、推挽输出、复用开漏输出和复用推挽输出。

    25f2de7ca006e110d23f2339e91d23c0.png

    1、模拟输入

    GPIO_Mode_AIN模拟输入,即关闭施密特触发器,将电压信号传送到片上外设模块(不接上下拉电阻)。

    2、浮空输入

    GPIO_Mode_IN_FLOATING浮空输入。浮空输入状态下,IO的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。

    3&4、上下拉输入

    GPIO_Mode_IPD下拉输入,GPIO_Mode_IPU上拉输入。一般来讲,上拉电阻为1K-10K,电阻越小,驱动能力越强。

    电阻的作用:防止输入端悬空,减少外部电流对芯片的干扰,限流,增加高电平输出时的驱动能力。

    当GPIO引脚无输入时,上拉输入在默认状态下为高电平,下拉输入在默认状态下为低电平。

    5、开漏输出

    GPIO_Mode_Out_OD开漏输出,输出端相当于三极管的集电极。要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对较强,一般20mA以内。

    6、推挽输出

    GPIO_Mode_Out_PP推挽输出,可以输出高、低电平,连接数字器件。

    7&8、复用开漏推挽输出

    GPIO_Mode_AF_OD复用开漏输出,GPIO_Mode_AF_PP复用推挽输出。可以理解为GPIO口被用作第二功能时的配置情况,即并非作为通用IO口使用。

    IO模式选用

    浮空输入:可以做KEY识别,RX1。

    上拉输入:IO内部上拉电阻输入。

    下拉输入:IO内部下拉电阻输入。

    模拟输入:应用ADC模拟输入,或者低功耗下省电。

    开漏输出:IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能。

    094f9a124aea41fe454c64c8975c4c66.png

    推挽输出:IO输出0-接GND,IO输出1 -接VCC,读输入值是未知的。

    复用推挽输出:片内外设功能,I2C的SCL、SDA。

    复用开漏输出:片内外设功能,TX1,MOSI,MISO.SCK.SS。

    引脚配置方式

    通常有5种方式使用某个引脚功能,它们的配置方式如下:

    1、作为普通GPIO输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。

    2、作为普通GPIO输出:根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。

    3、作为普通模拟输入:配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。

    4、作为内置外设的输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。

    5、作为内置外设的输出:根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块。

    展开全文
  • 在学习IO口之前,首先来复习一下之前学习的PIC16F887系列的封装图 第一节:IO口的基本知识介绍 数据方向控制器—TRISX IO口就是input/output口,用于单片机连接外部电路或者外部电路连接单片机 887有35个O口,36个I...
  • 通过第一篇的驱动解析,我们大概能知道普通io口按键一般的分类以及工程中的实际原理图,第二个就是知道怎么利用芯片本身自带的定时器以及主循环中断来检测按键按下以及通过按下的时间以及松手的检测来判断。...
  • 一、IO口的输入 1.分类 (1)基本输入IO电路 (2)施密特触发输入电路 (3)弱上拉输入电路 2.各种的优缺点 (1)基本输入IO电路 1>优点:不接VCC,GND,在低功耗模式下,不费电。 2>缺点...
  • 80C51单片机的四组IO口

    2022-01-03 15:17:22
    四组IO口的简介二. 问题导向1. 双向三态IO和准双向IO什么意思?2. 什么是LSTTL型负载?3. 为什么P0口可以带8个负载而其他是4个?三. 参考附录 一. 四组IO口的简介 单片机的IO口 类型 驱动负载数 其他功能 P...
  • 51单片机开发入门(3)-IO口应用

    千次阅读 2021-06-10 08:20:06
    IO口在经过前面两张文章尤其第51单片机开发入门(2)的介绍已经比较完善,在51单片机里共计有四组单片机IO口,对应的功能、理论知识前面可以进行查阅。我们整篇文章将阐述怎么利用它,以及利用它来实现什么功能。 一...
  • 1.IO:与 磁盘,文件,网络接口 等 系统共享资源,之间建立通道,并且传输数据的行为 叫 IO IO分为 inputStream 和 OutputStream,一个IO指令操作,可能是I,可能是O(例如 写文件),可能是IO(例如 网络请求) 2.IO...
  • IO口字节流

    2022-06-01 10:11:36
    我们可以对它进行如下分类: 1. 按处理的数据类型可分为字节流(byte)与字符流(char) 2. 按流的流向可分为输入流(in)与输出流(out) 3. 按流的功能可分为节点流(Node)和过滤流(Filter) 本篇侧重于梳理字节流相关...
  • IO口分类:ADC、SPI、PWM 资料的查看 每个IO口功能标注,每个IO的复用功能,都已经体现在原理图上了(重映射除外)。 重映射部分仅对F103有效,F4无此设置。 重映射关系可以查看数据手册的引脚描述表,也可以看...
  • STM32设置IO口输入上拉下拉

    万次阅读 多人点赞 2020-05-01 20:37:03
    1、按键分类 WK_UP按键按下时将高电平信号输入给STM32的IO,即高电平有效;...根据实际需要,为保证WK_UP不被按下时,STM32能够确定检测到IO口是低电平,所以设置接入下拉电阻。 2、上拉电阻和下拉电阻 上拉电阻...
  • 一、信号分类:  1、数字信号:物理量的变化在时间和幅值上都是离散的(不连续),反映在电路上就是高电平和低电平两种状态(即只有0和1两个逻辑值)。比如:灯有亮和不亮两种状态,天气有晴天和雨天两种状态,...
  • STM3216位IO口操作的一些教训 yuanmeixiang 2017-05-05 20:12:24 8783 收藏 9 分类专栏: STM32 文章标签: stm32 8位操作 版权 最近在用TFT屏的时候走啦不少弯路,因为TFT屏都是16位的,所以大部分的都是采用一组...
  • 常见IO接口标准之FPGA

    千次阅读 2021-04-29 20:23:20
    经计算,图像数据流接口速率需要数百兆比特/秒,因此需要调研FPGA支持的常见IO接口标准,及每种接口的应用场合。现在项目使用的FPGA芯片为Spartan6系列,故参考的user guide为UG381,《Spartan-6 FPGA SelectIO ...
  • 关于接口的简介及 vivado 的IO口约束

    万次阅读 2018-08-10 10:04:29
    文章内容部分转自:...刚做项目的时候,往往会忽略IO口的约束。每次稍微改动一些东西,就会发现 编译的结果不是自己想要的。 这样的现象...
  • 本篇粗浅介绍了什么是中断,中断的分类,中断中外部IO中断的应用步骤,浅薄的理解了外部IO中断实验,如有不对之处还请批评指正。httpshttpshttps。
  • 简介 最近在看了点32的东西,之前就学习过,现在相当于是个复习吧,因为是之前别人整理的pdf,未标明出处。...GPIO 的配置分类 (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入 (3)GPIO_Mo
  • 输入输出设备 —— IO接口

    千次阅读 2021-10-07 15:16:30
    IO接口的分类 1.IO接口的结构和作用 (1)IO接口的概念 IO接口概念: IO接口作用: (2)IO接口工作原理 IO接口结构: IO接口工作原理: 2.IO端口 (1)IO端口概念 (2)IO端口编址方式 3....
  • 目录 1、单片机IO口的结构 2、上下拉电阻 3、电机 3.1 电机分类 3.2 28BYJ-48型步进电机 3.2 28BYJ-48电机转动原理 3.3 28BYJ-48电机工作模式 3.4 步进电机启动频率 3.5 实际28BYJ-48电机外部转轮转一圈的情况 4、...
  • 摘要:读完本章节,您对java 的IO流有更清晰深刻的认识,对适配器模式、装饰模式也有初步的了解。一、关于流引用百度百科上的解释:流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据...
  • java io详解(1)

    2021-03-10 02:00:57
    一.java io结构图流分类:1.Java的字节流InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。2.Java的字符流Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。...
  • 外设IO原理

    2019-11-23 09:18:43
    外设IO原理 外设一般是指除了CPU、内存之前的其他接入到计算机的设备,比如硬盘、光驱、鼠标、...IO设备分类     I/O设备大概分为两种:块设备和字符设备。     块设备:...
  • 深入理解Java中的IO

    千次阅读 2021-02-12 22:56:33
    深入理解Java中的IO转载自:http://blog.csdn.net/qq_25184739/article/details/51205186本文的...流的概念和作用2.Java IO所采用的模型 :3.IO流的分类4.Java IO流对象1.输入字节流InputStream2.输出字节流OutputStr...
  • IO接口和设备控制器.ppt操作系统 Operating System 教学目的 通过对本章地讲解是学生理解并掌握设备管理的功能、I/O控制方式、缓冲区管理、设备管理,以及磁盘存储管理。 本章重点: 输入输出控制方式 缓冲区的管理 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,556
精华内容 3,022
关键字:

io口分类