GPIO模拟I2C程序实现

发布者:baiyuguoji最新更新时间:2018-05-20 来源: eefocus关键字:GPIO  模拟I2C 手机看文章 扫描二维码
随时随地手机看文章

GPIO模拟I2C程序实现.

I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。I2C是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。
I2C数据格式如下:
无数据:SCL=1,SDA=1;
开始位(Start):当SCL=1时,SDA由1向0跳变;
停止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;
当SCL保持为0时,SDA上的数据可随意改变;
地址位:定义同数据位,但只由Master发给Slave;
应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;
否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。
当数据为单字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。
当数据为一串字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。
需要注意的是:
1,SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2,开始位“Start”和停止位“Stop”,只能由Master来发出。
3,地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
4,当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
5,当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6,当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。

7,I2C规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收据

定义为接收器。主器件和从器件都可以工作于接收和发送状态。 总线必须由主器件(通常

为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止

条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA

状态的改变被用来表示起始和停止条件。

 


在实际应用中,并没有强制规定数据接收方必须对于发送的8位数据做出回应,尤其是在Master和Slave端都是用GPIO软件模拟的方法来实现的情况下,编程者可以事先约定数据传送的长度,不发送ACK,有时可以起到减少系统开销的效果。

源码:

/********************************************************************/

void i2c_init(void)
{
PACNT_init;
PADDR_init;
PADAT_init;

SCL_high;
SDA_high;
}

/********************************************************************/

uint8 i2c_write(uint8 slave_address, uint8 *buffer, int byte_count, int freq)
{
    uint8 out_mask = 0x80;
    uint8 value = 0x00;
  uint8 send_byte = 0x00;
  uint8 status = 0x81;
  int count = 8;
  int clk_count = 0;
int i = 0;

/* Set delay value based on frequency. */
int D = (int) ((4000/freq) - 14);

slave_address = (slave_address & 0xFE);
         
  i2c_start();
  delay(500);
  
   send_byte = slave_address;
        
   for(i = 0; i <= byte_count; i++)
   {    
    count = 8;  
    out_mask = 0x80;
         
    /* Send data bytes one bit at a time. */   
    while(count > 0)
    {            
     value = ((send_byte & out_mask) ? 1 : 0);
      if (value == 1)
      {
       PADAT_init;
        SDA_high;}
      else
      {
       PADAT_init;
       SDA_low;}
       
      delay(D);     
                   
        PADAT_init;
      SCL_high;
      
      /* Clock stretching wait statement.  Wait until clock is released
      by slave.  Only effects program on first iteration.  */
   while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}

      delay(2*D);  
       
      PADAT_init;
      SCL_low;
      delay(D); 
       
      out_mask >>= 1; 
      count--;   
     }
     
     PADAT_init;
     SDA_high;  /* Let go of data pin. */
     delay(D); 
      
     if (((GPIO_PADAT & 0x0400) ? 1 : 0) == 1)
     { 
      status = 0xA1; /* Transfer complete, bus busy, acknowledge not received. */
      break; } /* If not acknowledged, exit loop. */
     
    PADAT_init;
     SCL_high;
     delay(2*D);  
    
     PADAT_init;
     SCL_low;
     status = 0xA0;  /* Transfer complete, bus busy, acknowledge received. */
     delay(D); 
     
     send_byte = buffer[i];      
    }
    
    PADAT_init;
    SDA_high;
    SCL_low;   
delay(100);
return(status);
}

/********************************************************************/

uint8 i2c_read(uint8 slave_address, uint8 *buffer, int byte_count, int freq)
{
uint8 input_byte = 0x00;
uint8 value = 0x00;
uint8 out_mask = 0x80;
uint8 status = 0x81;
int count = 8;
int clk_count = 0;
int i = 0;

/* Set delay value based on frequency. */
int D = (int) ((4000/freq) - 14);

slave_address = (slave_address | 0x01);
   
i2c_start();
delay(500);
               
/**********  Write Address Procedure **********/
  
   while(count > 0)
   {
    value = ((slave_address & out_mask) ? 1 : 0);
     if (value == 1)
     {
      PADAT_init;
       SDA_high;}
     else
     {
      PADAT_init;
      SDA_low;}
      delay(D);      
                   
      PADAT_init;
     SCL_high;
      
     /* Clock stretching wait.  Wait until clock is released
     by slave.  */
     while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}

     delay(2*D); 
       
     PADAT_init;
     SCL_low;
     delay(D);  
       
     out_mask >>= 1; 
     count--;         
  }
     
    PADAT_init;
  SDA_high;  /* Let go of data pin. */
    delay(D);
    SCL_high;
    delay(2*D);  
    
    /* If not acknowleged, set status accordingly and exit read process. */
    if (((GPIO_PADAT & 0x0400) ? 1 : 0) == 1)
    {
     status = 0xA1;
     return(status);}
    
    PADAT_init;
    SCL_low;
    delay(D);

/**********  Begin Read Procedure **********/

/* Release SDA and SCL to initiate transfer. */
PADAT_init;    
SDA_high;
SCL_high;

for(i = 0; i < byte_count; i++)
{
  count = 8;
  input_byte = 0x00;
   
  PADAT_init;
  SCL_high;
   
  /* Clock stretching wait.  Wait until clock is released
     by slave.  */
  while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}
           
  /* Loop for bit-by-bit read of data. */
  while(count > 0) 
  {
    PADAT_init;
    SCL_high;
    delay(D);  
    delay(4); /* Required to make read and write clocks the same freq. */
    
   if ((GPIO_PADAT & 0x0600) == 0x0600)
    input_byte++;
  
   delay(D);  
   
   PADAT_init;
   SCL_low;
   delay(2*D); 
      
   if (count == 1)
    break;
   else  
    input_byte <<= 1;
  
   count--;
  }

  /* Write input byte to "read_buffer". */
  buffer[i] = input_byte;
    
  if(i == (byte_count - 1))
   break;
     
     /* Below is the acknowledge procedure. */     
     PADAT_init;
     SDA_low;
     delay(D);  
     SCL_high;     
  delay(2*D);  
    
     PADAT_init;
     SCL_low;
     delay(D);  
     SDA_high; 
     status = 0xA0; 
}     

/* Standard protocol calls for the last read byte to
    not receive an acknowledge from the master. */     
PADAT_init;
    SDA_high;
    SCL_high;     
delay(2*D); 
     
   PADAT_init;
   SCL_low;
   delay(D);  
   SDA_high;
   status = 0xA1;
   return(status);
}

/********************************************************************/

void i2c_start(void)
{
int clk_count = 0;
uint8 compare = 0x00;

PADAT_init;  
SDA_high;
delay(100);

PADAT_init;  
SCL_high;
delay(100);

/* Clock stretching wait.  Wait until clock is released
    by slave.  */
while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}    
  
PADAT_init;
SDA_low;
delay(100);
     
    PADAT_init;  
SCL_low;
delay(100);
}

/********************************************************************/

uint8 i2c_stop(void)
{
uint8 status = 0x00;
int clk_count = 0;
  
PADAT_init;
SCL_low;
delay(100);

PADAT_init;
SDA_low;
delay(100);
    
    PADAT_init; 
SCL_high;

/* Clock stretching wait statement.  Wait until clock is released
    by slave.  */
while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}
      
delay(100);
    
    PADAT_init; 
SDA_high;
status = 0x81; /* Set bus idle. */
return(status);
}

/********************************************************************/

void delay(int value)
{
int clk_count = 0;
while (clk_count < value)
{clk_count++;}
}

/********************************************************************/

 

第二个例子

函数定义:

gpio_iic.h:

#ifndef __IIC_GPIO__
#define __IIC_GPIO__
void delay();
/*
设置scl引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。
*/
int set_scl( int value );

/*
得到scl引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。
*/
int get_scl();

/*
设置sda引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。
*/
int set_sda( int value );

/*
得到sda引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。
*/
int get_sda();


/*
重新发送iic start位,这个是在传送数据过程中使用。
*/
void iic_restart();

/*
发送iic start位,这里假设总线空闲,此时SDL与SCL都为高电平。
*/
void iic_start();

/*
发送stop位,这里假设scl此时为低电平。
*/
void iic_stop();

/*
发送一个bit0,这里假设scl此时为低电平,sda电平不定。
*/
void send_bit0();

/*
发送一个bit 1,这里假设scl此时为低电平,sda电平不定。
 */
void send_bit1();

/*
接收一个bit位,返回值只能是0或1。
 */
int receive_bit();

/*
发送ACK,实际上是发送一个bit0.
*/
void send_ack();

/*
接收ACK。
*/
int receive_ack();

/*
接收一个字节。
*/
char receive_byte();

/*
接收一个buf,返回值总是为0,它不能保证从器件一定能收到ACK,也不能保证从器件正在工作。
*/
int receive_buf( char *buf, int buf_size );

/*
发送一个字节,返回ACK的值,发送时,没有收到ACK会重试n次,这是常。
 */
int send_byte( char data_byte );

/*
发送一个buf,返回值是成功发送,收到ACK的字节数量。
*/
int send_buf( char *buf, int buf_size );

#endif


gpio_iic.c:

#include "gpio_iic.h"
//#define __80C52__
#define __MINI2440__
#ifdef __MINI2440__
#include
#include
#include
#endif

#ifdef __80C52__
#include
sbit SCL  = P1^0;
sbit SDA    = P1^1;
#endif


void delay()
{
#ifdef __MINI2440__
     udelay(1);
#endif
#ifdef __80C52__
     int i = 0;
     for( i = 0; i < 10000; i ++ );
#endif
}
/*
设置scl引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。
*/
int set_scl( int value )
{

#ifdef __MINI2440__
//    s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
//     s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
     s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
     switch( value )
     {
     case 0:
      s3c2410_gpio_setpin(S3C2410_GPE(14), 0); // IICSCL
      break;
     case 1:
      s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL
      break;
     default:
      break;
     }
#endif

#ifdef __80C52__
     if ( 0 == value )
      SCL = 0;
     else if ( 1 == value )
      SCL = 1;
#endif
     return 0;                  
}


/*
得到scl引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。
*/
int get_scl()
{
#ifdef __MINI2440__
     s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_INPUT);
     return s3c2410_gpio_getpin(S3C2410_GPE(14)) > 0 ? 1: 0;
#endif

#ifdef __80C52__
     return SCL;
#endif
}

 

/*
设置sda引脚电平,0低电平,1高电平,其他值无效,返回值一直为0,留着它用。
*/
int set_sda( int value )
{
#ifdef __MINI2440__
     s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
     switch( value )
     {
     case 0:
      s3c2410_gpio_setpin(S3C2410_GPE(15), 0); // IICSDA
      break;
     case 1:
      s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA
      break;
     default:
      break;
     }
#endif
#ifdef __80C52__
     if ( 0 == value )
      SDA = 0;
     else if ( 1 == value )
      SDA = 1;    
#endif        
     return 0;
}

 

/*
得到sda引脚电平,0低电平,1高电平,必须是这两个值,其他函数需要调用。
*/
int get_sda()
{
#ifdef __MINI2440__
     int sda_pin = 0;
     s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_INPUT);
     sda_pin = s3c2410_gpio_getpin(S3C2410_GPE(15)) > 0 ? 1:0;
     return sda_pin;
#endif
#ifdef __80C52__
     return SDA;
#endif
}


/*
重新发送iic start位,这个是在传送数据过程中使用。
*/
void iic_restart()
{
     set_scl( 0 );
     delay();
     set_sda( 1 );
     delay();
     set_scl( 1 );
     delay();
     set_sda( 0 );
     delay();
     set_scl( 0 );
     delay();
}


/*
发送iic start位,这里假设总线空闲,此时SDL与SCL都为高电平。
*/
void iic_start()
{
     set_sda( 0 );
     delay();
     set_scl( 0 );
     delay();
}

/*
发送stop位,这里假设scl此时为低电平。
*/
void iic_stop()
{
     set_sda( 0 );
     delay();
     set_scl( 1 );
     delay();
     set_sda( 1 );        
     delay();
}


/*
发送一个bit0,这里假设scl此时为低电平,sda电平不定。
*/
void send_bit0()
{
     set_sda( 0 );
     delay();
     set_scl( 1 );
     delay();
     set_scl( 0 );
     delay();
}

/*
发送一个bit 1,这里假设scl此时为低电平,sda电平不定。
 */
void send_bit1()
{
     set_sda( 1 );
     delay();
     set_scl( 1 );
     delay();
     set_scl( 0 );
     delay();
}

/*
接收一个bit位,返回值只能是0或1。
 */
int receive_bit()
{
     int value = -1;

     set_sda( 1 );
     delay();
     set_scl( 0 );
     delay();
     set_scl( 1 );
     delay();
     value = get_sda();
     set_scl( 0 );
     return value;    
}

/*
发送ACK,实际上是发送一个bit0.
*/
void send_ack( )
{
     send_bit0();
}

/*
接收ACK。
*/
int receive_ack()
{
     int ack = 1;
     set_sda( 1 );
     delay();
     set_scl( 1 );
     delay();
     ack = get_sda();        
     delay();
     set_scl( 0 );
     return ack;
}

/*
接收一个字节。
*/
char receive_byte( )
{
     int i = 0;
     int recv_data = 0;
     for ( i = 0; i < 8; i++ )
     {
      recv_data = recv_data | receive_bit();
      if ( 7 == i )
           break;
      recv_data <<= 1;
     }
     send_ack();
     return recv_data;    
}

/*
接收一个buf,返回值总是为0,它不能保证从器件一定能收到ACK,也不能保证从器件正在工作。
*/
int receive_buf( char *buf, int buf_size )
{
     int i = 0;
     for( i = 0; i < buf_size; i ++ )
     {
      buf[i] = receive_byte();
     }
     return buf_size;
}

/*
发送一个字节,返回ACK的值,发送时,没有收到ACK会重试n次,这是常。
 */
int send_byte( char data_byte )
{
     int retry_count = 8;//重试次数。
     int i = 0;
     int ack = 1;        
     char send_data = 0;
     send_data = data_byte;
     do{
      for ( i = 0; i < 8; i ++ )
      {
           if ( 0x80 & send_data )
            send_bit1();
           else
            send_bit0();
           send_data <<= 1;
      }
      ack = receive_ack();
      if ( 0 == ack )
           break;
      send_data = data_byte;
      retry_count --;
     }
     while( retry_count >= 0 );
     return ack;
}

/*
发送一个buf,返回值是成功发送,收到ACK的字节数量。
*/
int send_buf( char *buf, int buf_size )
{
     int i = 0;
     int count = 0;
     for ( i = 0; i < buf_size; i ++ )
     {
      if (0 != send_byte( buf[i] ) )
           break;
      count ++;
     }
     return count;        
}

 

下面是可以用来读写at24c02的测试代码,在mini2440板测试通过,

static void m24c02_send( int addr, char *buf,  int buf_size)
{
     int count = 0;
     int rev = -1;
    iic_start();
    rev = send_byte( 0xa0 );
    rev = send_byte( (addr >> 0) & 0xff );
    count = send_buf( buf, buf_size );
    iic_stop();
 
}

static void m24c02_recv( int addr , char *buf, int buf_size )
{
      iic_start();
    send_byte( 0xa0 );
    send_byte( (addr >> 0) & 0xff );
      iic_restart();
    send_byte( 0xa1 );
    receive_buf( buf, buf_size );
    iic_stop();

 

 

(1)基础宏定义

#define GPIO_SCL             S3C2410_GPF3

#define GPIO_SDA             S3C2410_GPF0

#define GPIO_SDA_OUTP   S3C2410_GPF0_OUTP  //设定SDA输出

#define GPIO_SDA_INP      S3C2410_GPF0_INP     //设定SDA输入

#define GPIO_SCL_OUTP   S3C2410_GPF3_OUTP  //设定SCL输出

void I2C_SCL_OUTP( void )

{

      s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);

}

void I2C_SCL_Output(u8 value)

{

      if(value)

      {                                               

            s3c2410_gpio_setpin(GPIO_SCL,value); 

      }

      else

      {

            s3c2410_gpio_setpin(GPIO_SCL,value ); 

      }

}

void I2C_SDA_Mode(u8 v_mode)   //SDA输出方向

{

       if(v_mode)

       {                                               

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP);  

       }

       else

       {

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP);  

       }

}

void I2C_SDA_Output(u8 value)

{

       if(value)

       {                                               

               s3c2410_gpio_setpin(GPIO_SDA,value); 

       }

       else

       {

                s3c2410_gpio_setpin(GPIO_SDA,value ); 

       }

}

u8 I2C_SDA_Read(void)    //SDA读数据

{

       return s3c2410_gpio_getpin(GPIO_SDA); 

}

(2)基础段

void I2C_Init(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);      //默认拉高

}

void I2C_Wait(void)

{

      u16 i;

      for(i=0;i<200;i++);

}

void I2C_Start(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(0);

}

void I2C_Stop(void)

{

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(1);

}


 

(3)读写单个字节的段

u8 I2C_Send_Byte(u8 bytedata)

{

      u8 i,ack;

      I2C_SDA_Mode(1);  //SDA输出

      I2C_SCL_OUTP();

      for (i = 0; i < 8; i++) 

      {

              if (bytedata & 0x80)

              {

                     I2C_SDA_Output(1);

              }

              else

              {

                    I2C_SDA_Output(0);

              }

              bytedata <<= 1;

            

              I2C_SCL_Output(1);

              udelay(3);

              I2C_SCL_Output(0);

              udelay(1);

       }    

  

        I2C_SDA_Output(1);  //release

        udelay(3);

       

        I2C_SDA_Mode(0);  //设定SDA输入

        I2C_SCL_Output(1);  

        udelay(3);

        ack = I2C_SDA_Read();   //读应答

        I2C_SDA_Mode(1);

        I2C_SCL_Output(0);

        udelay(3);

      

        return ack;  

}

u8 I2C_Receive_Byte(void) 

{

       u8 i;

       u8 bytedata = 0x00;

       u8 temp;

       I2C_SDA_Mode(0);

       for ( i = 0; i < 8; i++)

       {

             I2C_SCL_Output(1);

             udelay(3);

             bytedata <<= 1;

             temp = I2C_SDA_Read();

             printk("reda SDA'value is:%d\n",temp);

             if (temp)

                   bytedata |= 0x01;

             printk("  bytedata is:%x\n",bytedata);

             I2C_SCL_Output(0);

             udelay(1);

       }

       I2C_SDA_Mode(1);

       return bytedata;

}

(4)读写单个字节的I2C应用函数

u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata)

{  

       u8 ack;

       printk("device_ID is:%x\n",device_ID);

       printk("address is:%x\n",address);

       printk("date is:%x\n",bytedata);

       I2C_Start(); 

       ack=I2C_Send_Byte(device_ID);

       printk("ack is:%d\n",ack);

       if(ack)

             I2C_Stop();

       I2C_Send_Byte(address);

       I2C_Send_Byte(bytedata);

       I2C_Stop();

       I2C_Wait();

       return 0;

}

u8 I2C_Byte_Read(u8 device_ID,u8 address)

{  

       u8 bytedata;

       I2C_Start();

       I2C_Send_Byte(device_ID);

       I2C_Send_Byte(address);

       I2C_Start();

       I2C_Send_Byte(device_ID+1);

       bytedata = I2C_Receive_Byte();  //读单个字节,不需要再发应答

       I2C_Stop();   

       return bytedata;

}


关键字:GPIO  模拟I2C 引用地址:GPIO模拟I2C程序实现

上一篇:I2C的主机从机模拟
下一篇:普通IO口模拟实现I2C通信及应用解析

推荐阅读最新更新时间:2024-03-16 16:03

STM32CubeMx GPIO基本使用方法
第一点:生成一个工程后,需要注意事项: 在STM32CubeMx软件本身生成的源文件中; 用户的代码只可以写在以下区域,自己建立的源码文件不受影响: //写在前面或后面在下次从STM32CubeMx 生成工程时会被清空掉! //包含库文件,所以尽量不要试图尝试修改库文件来达到功能需求! USER CODE BEGIN //只有这写在有编辑权限的代码区域中编写代码,才不会被清空掉,这里要注意一下! 用户可编写的代码区 USER CODE END int main(void) { /* USER CODE BEGIN 1 */ 用户可编写的代码区 /* USER CODE END 1 */ /* MC
[单片机]
msp430单片机GPIO基础理解
单片机的端口可以通过方向寄存器PxDIR来设置输出(1)还是输入(0) 可以通过输入寄存器PxIN来查看输入端口引脚的电平,尝用来判断按键是否按下。 也可通过PxIE,PxIES,PxIFG实现按键中断,按下某键后执行一段中断程序。 可通过输出寄存器PxOUT来写入输出,常用来控制数码管显示和指示灯等输出设备显示。 PxOUT |= BIT0;//不影响x端口其他引脚而设置x.0引脚输出1 PxOUT &= ~BIT0;//不影响x端口其他引脚而设置x.0引脚输出0 BIT0等价于0x01 0000 0001 BIT7等价于1000 0000 if(!(PxIN & BIT0))判断x.0引脚是否按下 定时器要设置时钟源,捕获/比
[单片机]
基础——STM32F4的GPIO模式
stm32的GPIO的配置模式包括: 1. 模拟输入; 2. 浮空输入; 3. 上拉输入; 4. 下拉输入; 5. 开漏输出; 6. 推挽输出; 7. 复用开漏输出; 8. 复用推挽输出 1.模拟输入 从上图我们可以看到,我觉得模拟输入最重要的一点就是,他不经过输入数据寄存器,所以我们无法通过读取输入数据寄存器来获取模拟输入的值,我觉得这一点也是很好理解的,因为输入数据寄存器中存放的不是0就是1,而模拟输入信号不符合这一要求,所以自然不能放进输入数据寄存器。该输入模式,使我们可以获得外部的模拟信号。 2.浮空输入 该输入状态,我的理解是,它的输入完全由外部决定,我觉得在数据通信中应该可以使用该模式。应为在数
[单片机]
基础——STM32F4的<font color='red'>GPIO</font>模式
ARM--GPIO端口
s3c2440共有130个GPIO端口,分为9组,GPA ~ GPJ,通过寄存器控制。 控制s3c2440的GPIO端口的寄存器有3类,分别是GPxCON、GPxDAT、GPxUP (x=A ~ J): GPxCON:GPIO控制寄存器,可以设置选定GPIO口的输入输出方式和功能。GPA组的23个端口比较特殊,只能是输出方式。GPACON的每一位对应一个引脚,当某位为0时,对应引脚为输出端口,否则为复用功能。 GPB ~ GPJ端口的GPxCON寄存器使用方法一致,每两位控制一个引脚,00时为输入I/O口,01时为输出I/O口,10时为复用功能,11保留。 GPxDAT:此引脚用于读写引脚的状态,即端口数据。当引脚配置
[单片机]
stm32 GPIO原理: 输入和输出控制
pre name= code class= html #include stm32f10x.h int main(void) { //1.PA.0 工作在推揽输出,50MHZ; PA.8输入 浮空输入 GPIOA- CRL=0X03; GPIOA- CRH=0X04; //2. PA.0 输出 = PA.8输入 while(1){ if((GPIOA- IDR&0X0100)==0X0100) GPIOA- ODR=0X01; else GPIOA- ODR=0x00; } return 0; }
[单片机]
STM32CubeMX学习教程之一:GPIO输出之跑马灯
完整源码下载: https://github.com/simonliu009/STM32CubeMX-GPIO-Control 软件版本: STM32CubeMX V4.25.0 System Workbench V2.4 固件库版本: STM32Cube FW_F1 V1.6.1 硬件:OneNet 麒麟座V2.3 在STM32CubeMX中新建项目,选择正确的MCU型号 首先设置RCC和SYS,如下图 然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M),如下图 GPIO设置 PC7, PC8, PA12和 PC10为GPIO_OUTPUT, (这是麒麟座V2.3的四
[单片机]
STM32菜鸟成长记录---GPIO的使用
#include stm32f10x_lib.h #include stm32f10x.h GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO宏操作结构体 void Delay(__IO uint32_t nCount)//__IO的宏定义volatile { for(; nCount != 0; nCount--); } /*初始化嵌入式Flash接口,初始化PLL使其达到系统可用频率*/ void RCC_Configuration(void) { /* Setup the microcontroller system. Initialize the Embedd
[单片机]
STM32菜鸟成长记录---<font color='red'>GPIO</font>的使用
Atmel 的触摸式控制器整合LED和GPIO
Atmel(C) Corporation 今天宣布推出在单个设备中整合触摸式按键和触摸式滚动条功能的触摸式控制器集成电路 -- AT42QT2160。它能够通过一个由2到8个触摸式按键通道组成的滚动条控制多达16个独立的触摸式按键。此外,该芯片还能够通过由主机控制的脉宽调制输出功能控制多达11个发光二极管 (LED),因而不再需要一个外部 LED 控制器。 由于结合了这些功能,该设备很适合用作移动电话以及个人媒体播放器等消费应用产品中的多媒体 HMI 控制器,它能够节约空间,最大程度地缩短设计时间,并让设计者在设计控制按键时有足够的发挥空间。该设备支持的电压范围广(1.8V 至 5.5V 直流电),功率要求低,十分适用于其它
[手机便携]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved