版权声明:本文为博主原创文章,允许转载,但希望标注转载来源。 https://blog.csdn.net/qq_38410730/article/details/80312357

IIC的基本介绍

IIC的简介

IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。

  • IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
  • IIC总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

STM32的IIC接口

目前绝大多数的MCU都附带IIC总线接口,STM32也不例外。但是在本文中,我们不使用STM32的硬件IIC来读取24C02,而是通过软件的方式来模拟。

原因是因为:STM32的硬件IIC非常复杂,更重要的是它并不稳定,故不推荐使用。

IIC协议

IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。

先来看一下IIC总线的时序图:

这可能会比较复杂,可以先看一份简化了的时序图:

空闲状态

当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

起始信号与停止信号

  • 起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;
  • 停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

应答信号

发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。

数据有效性

IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

数据的传达

在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

延时时间

IIC总线的数据传送

IIC总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(地址通过物理接地或者拉高),主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。

也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。

  • 主设备往从设备中写数据。数据传输格式如下:

淡蓝色部分表示数据由主机向从机传送,粉红色部分则表示数据由从机向主机传送。

写用0来表示(低电平),读用1来表示(高电平)。

  • 主设备从从设备中读数据。数据传输格式如下:

在从机产生响应时,主机从发送变成接收,从机从接收变成发送。之后,数据由从机发送,主机接收,每个应答由主机产生,时钟信号仍由主机产生。若主机要终止本次传输,则发送一个非应答信号,接着主机产生停止条件。

  • 主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:

在多主的通信系统中,总线上有多个节点,它们都有自己的寻址地址,可以作为从节点被别的节点访问,同时它们都可以作为主节点向其它的节点发送控制字节和传送数据。但是如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I2C总线上的仲裁。

I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。

这部分就暂时不介绍了,想要了解:可以参考链接浅谈I2C总线或I2C总线协议图解。

IIC底层驱动程序分析

现拟采用PB6、PB7来模拟IIC时序,其中:PB6为时钟线,PB7为数据线。

首先进行一些必要的宏定义:

  1. //IO方向设置
  2. #define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
  3. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
  4. //IO操作函数
  5. #define IIC_SCL PBout(6) //SCL
  6. #define IIC_SDA PBout(7) //SDA
  7. #define READ_SDA PBin(7) //输入SDA
  8. //IIC所有操作函数
  9. void IIC_Init(void); //初始化IIC的IO口
  10. void IIC_Start(void); //发送IIC开始信号
  11. void IIC_Stop(void); //发送IIC停止信号
  12. void IIC_Send_Byte(u8 txd); //IIC发送一个字节
  13. u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  14. u8 IIC_Wait_Ack(void); //IIC等待ACK信号
  15. void IIC_Ack(void); //IIC发送ACK信号
  16. void IIC_NAck(void); //IIC不发送ACK信号

由于IIC是半双工通信方式,因而数据线SDA可能会数据输入,也可能是数据输出,需要定义IIC_SDA来进行输出、READ_SDA来进行输入,与此同时就要对IO口进行模式配置:SDA_IN()和SDA_OUT()。

而时钟线SCL一直是输出的,所以就没有数据线SDA麻烦了。

  1. //初始化IIC
  2. void IIC_Init(void)
  3. {
  4. GPIO_InitTypeDef GPIO_InitStructure;
  5. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟
  6. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
  7. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
  8. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9. GPIO_Init(GPIOB, &GPIO_InitStructure);
  10. GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高,空闲状态
  11. }
  12. //产生IIC起始信号
  13. void IIC_Start(void)
  14. {
  15. SDA_OUT(); //sda线输出
  16. IIC_SDA=1;
  17. IIC_SCL=1;
  18. delay_us(4);
  19. IIC_SDA=0;    //START:when CLK is high,DATA change form high to low
  20. delay_us(4);
  21. IIC_SCL=0;    //钳住I2C总线,准备发送或接收数据
  22. }
  23. //产生IIC停止信号
  24. void IIC_Stop(void)
  25. {
  26. SDA_OUT();    //sda线输出
  27. IIC_SCL=0;
  28. IIC_SDA=0;    //STOP:when CLK is high DATA change form low to high
  29. delay_us(4);
  30. IIC_SCL=1;
  31. IIC_SDA=1;    //发送I2C总线结束信号
  32. delay_us(4);
  33. }
  34. //发送数据后,等待应答信号到来
  35. //返回值:1,接收应答失败,IIC直接退出
  36. // 0,接收应答成功,什么都不做
  37. u8 IIC_Wait_Ack(void)
  38. {
  39. u8 ucErrTime=0;
  40. SDA_IN(); //SDA设置为输入
  41. IIC_SDA=1;delay_us(1);
  42. IIC_SCL=1;delay_us(1);
  43. while(READ_SDA)
  44. {
  45. ucErrTime++;
  46. if(ucErrTime>250)
  47. {
  48. IIC_Stop();
  49. return 1;
  50. }
  51. }
  52. IIC_SCL=0;    //时钟输出0
  53. return 0;
  54. }
  55. //产生ACK应答
  56. void IIC_Ack(void)
  57. {
  58. IIC_SCL=0;
  59. SDA_OUT();
  60. IIC_SDA=0;
  61. delay_us(2);
  62. IIC_SCL=1;
  63. delay_us(2);
  64. IIC_SCL=0;
  65. }
  66. //不产生ACK应答
  67. void IIC_NAck(void)
  68. {
  69. IIC_SCL=0;
  70. SDA_OUT();
  71. IIC_SDA=1;
  72. delay_us(2);
  73. IIC_SCL=1;
  74. delay_us(2);
  75. IIC_SCL=0;
  76. }
  77. //IIC发送一个字节
  78. //返回从机有无应答
  79. //1,有应答
  80. //0,无应答
  81. void IIC_Send_Byte(u8 txd)
  82. {
  83. u8 t;
  84. SDA_OUT();
  85. IIC_SCL=0;            //拉低时钟开始数据传输
  86. for(t=0;t<8;t++)
  87. {
  88. //IIC_SDA=(txd&0x80)>>7;
  89. if((txd&0x80)>>7)
  90. IIC_SDA=1;
  91. else
  92. IIC_SDA=0;
  93. txd<<=1;
  94. delay_us(2);     //对TEA5767这三个延时都是必须的
  95. IIC_SCL=1;
  96. delay_us(2);
  97. IIC_SCL=0;
  98. delay_us(2);
  99. }
  100. }
  101. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  102. u8 IIC_Read_Byte(unsigned char ack)
  103. {
  104. unsigned char i,receive=0;
  105. SDA_IN();        //SDA设置为输入
  106. for(i=0;i<8;i++ )
  107. {
  108. IIC_SCL=0;
  109. delay_us(2);
  110. IIC_SCL=1;
  111. receive<<=1;
  112. if(READ_SDA)receive++;
  113. delay_us(1);
  114. }
  115. if (!ack)
  116. IIC_NAck();        //发送nACK
  117. else
  118. IIC_Ack();         //发送ACK
  119. return receive;
  120. }

这里是通过普通IO口(PB6、PB7)来模拟IIC时序的程序,其实本质上都是严格按照IIC的时序图进行的,认真读,仔细对比,应该是没有什么困难的。

就提一下:IIC_Read_Byte()函数,这个函数的参数表示读取一个字节之后,需要给对方应答信号或非应答信号。

普通IO口模拟IIC时序读取24C02

24C02芯片介绍

EEPROM (Electrically Erasable Programmable read only memory),带电可擦可编程只读存储器——一种掉电后数据不丢失的存储芯片。

24Cxx芯片是EEPROM芯片的一种,它是基于IIC总线的存储器件,遵循二线制协议,由于其具有接口方便,体积小,数据掉电不丢失等特点,在仪器仪表及工业自动化控制中得到大量的应用。24Cxx在电路的作用主要是在掉电的情况下保存数据。

本文使用的是24C02芯片,总容量是2k个bit(256个字节)。这里芯片名称里的02代表着总容量。

24C02芯片的引脚分布和具体的作用见下图:

24C02芯片的引脚说明
引脚名称 说明
A0-A2 地址输入线
SDA 数据线
SCL 时钟线
WP 写保护
GND、VCC 提供电源

下图是本文中24C02和STM32的引脚连接图:

从图中可以看出:A0、A1、A2都为0。

对于并联在一条IIC总线上的每个IC都有唯一的地址。那么看一下从器件地址,可以看出对于不同大小的24Cxx,具有不同的从器件地址。由于24C02为2k容量,也就是说只需要参考图中第一行的内容:

根据图中的内容:如果是写24C02的时候,从器件地址为10100000(0xA0);读24C02的时候,从器件地址为10100001(0xA1)。

24C02芯片的时序图

这部分的内容应结合上文:I2C总线的数据传送的内容一起理解。

24C02字节写时序

对24C02芯片进行写字节操作的时候,步骤如下:

  1. 开始位,后面紧跟从器件地址位(0xA0),等待应答,这是为了在IIC总线上确定24C02的从地址位置;
  2. 确定操作24C02的地址,等待应答,也就是将字节写入到24C02中256个字节中的位置;
  3. 确定需要写入24C02芯片的字节,等待应答,停止位。

24C02字节读时序

对24C02芯片进行读字节操作的时候,步骤如下:

  1. 开始位,后面紧跟从器件地址位(0xA0),等待应答,这是为了在IIC总线上确定24C02的从地址位置;
  2. 确定操作24C02的地址,等待应答,也就是从24C02中256个字节中读取字节的位置;
  3. 再次开始位,后面紧跟从器件地址位(0xA1),等待应答;
  4. 获取从24C02芯片中读取的字节,发出非应答信号,停止位。

读取24C02芯片程序

  1. #define AT24C01 127
  2. #define AT24C02 255
  3. #define AT24C04 511
  4. #define AT24C08 1023
  5. #define AT24C16 2047
  6. #define AT24C32 4095
  7. #define AT24C64 8191
  8. #define AT24C128 16383
  9. #define AT24C256 32767
  10. //Mini STM32开发板使用的是24c02,所以定义EE_TYPE为AT24C02
  11. #define EE_TYPE AT24C02
  1. //初始化IIC接口
  2. void AT24CXX_Init(void)
  3. {
  4. IIC_Init();
  5. }
  6. //在AT24CXX指定地址读出一个数据
  7. //ReadAddr:开始读数的地址
  8. //返回值 :读到的数据
  9. u8 AT24CXX_ReadOneByte(u16 ReadAddr)
  10. {
  11. u8 temp=0;
  12. IIC_Start();
  13. if(EE_TYPE>AT24C16)            //为了兼容24Cxx中其他的版本
  14. {
  15. IIC_Send_Byte(0XA0); //发送写命令
  16. IIC_Wait_Ack();
  17. IIC_Send_Byte(ReadAddr>>8);    //发送高地址
  18. IIC_Wait_Ack();
  19. }else     IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
  20. IIC_Wait_Ack();
  21. IIC_Send_Byte(ReadAddr%256); //发送低地址
  22. IIC_Wait_Ack();
  23. IIC_Start();
  24. IIC_Send_Byte(0XA1); //进入接收模式
  25. IIC_Wait_Ack();
  26. temp=IIC_Read_Byte(0);     //读一个字节,非应答信号信号
  27. IIC_Stop();        //产生一个停止条件
  28. return temp;
  29. }
  30. //在AT24CXX指定地址写入一个数据
  31. //WriteAddr :写入数据的目的地址
  32. //DataToWrite:要写入的数据
  33. void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
  34. {
  35. IIC_Start();
  36. if(EE_TYPE>AT24C16)
  37. {
  38. IIC_Send_Byte(0XA0); //发送写命令
  39. IIC_Wait_Ack();
  40. IIC_Send_Byte(WriteAddr>>8);    //发送高地址
  41. }else
  42. {
  43. IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
  44. }
  45. IIC_Wait_Ack();
  46. IIC_Send_Byte(WriteAddr%256); //发送低地址
  47. IIC_Wait_Ack();
  48. IIC_Send_Byte(DataToWrite); //发送字节
  49. IIC_Wait_Ack();
  50. IIC_Stop();    //产生一个停止条件
  51. delay_ms(10);
  52. }
  53. //在AT24CXX里面的指定地址开始写入长度为Len的数据
  54. //该函数用于写入16bit或者32bit的数据.
  55. //WriteAddr :开始写入的地址
  56. //DataToWrite:数据数组首地址
  57. //Len :要写入数据的长度2,4
  58. void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
  59. {
  60. u8 t;
  61. for(t=0;t<Len;t++)
  62. {
  63. AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
  64. }
  65. }
  66. //在AT24CXX里面的指定地址开始读出长度为Len的数据
  67. //该函数用于读出16bit或者32bit的数据.
  68. //ReadAddr :开始读出的地址
  69. //返回值 :数据
  70. //Len :要读出数据的长度2,4
  71. u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
  72. {
  73. u8 t;
  74. u32 temp=0;
  75. for(t=0;t<Len;t++)
  76. {
  77. temp<<=8;
  78. temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
  79. }
  80. return temp;
  81. }
  82. //检查AT24CXX是否正常
  83. //这里用了24XX的最后一个地址(255)来存储标志字.
  84. //如果用其他24C系列,这个地址要修改
  85. //返回1:检测失败
  86. //返回0:检测成功
  87. u8 AT24CXX_Check(void)
  88. {
  89. u8 temp;
  90. temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX
  91. if(temp==0X55)return 0;
  92. else//排除第一次初始化的情况
  93. {
  94. AT24CXX_WriteOneByte(255,0X55);
  95. temp=AT24CXX_ReadOneByte(255);
  96. if(temp==0X55)return 0;
  97. }
  98. return 1;
  99. }
  100. //在AT24CXX里面的指定地址开始读出指定个数的数据
  101. //ReadAddr :开始读出的地址 对24c02为0~255
  102. //pBuffer :数据数组首地址
  103. //NumToRead:要读出数据的个数
  104. void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
  105. {
  106. while(NumToRead)
  107. {
  108. *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
  109. NumToRead--;
  110. }
  111. }
  112. //在AT24CXX里面的指定地址开始写入指定个数的数据
  113. //WriteAddr :开始写入的地址 对24c02为0~255
  114. //pBuffer :数据数组首地址
  115. //NumToWrite:要写入数据的个数
  116. void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
  117. {
  118. while(NumToWrite--)
  119. {
  120. AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
  121. WriteAddr++;
  122. pBuffer++;
  123. }
  124. }
  1. //要写入到24c02的字符串数组
  2. const u8 TEXT_Buffer[]={"WarShipSTM32 IIC TEST"};
  3. #define SIZE sizeof(TEXT_Buffer)
  4. int main(void)
  5. {
  6. u8 key;
  7. u16 i=0;
  8. u8 datatemp[SIZE];
  9. delay_init(); //延时函数初始化
  10. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  11. uart_init(115200); //串口初始化为115200
  12. LED_Init(); //初始化与LED连接的硬件接口
  13. LCD_Init(); //初始化LCD
  14. KEY_Init(); //按键初始化
  15. AT24CXX_Init(); //IIC初始化
  16. POINT_COLOR=RED;//设置字体为红色
  17. LCD_ShowString(30,50,200,16,16,"WarShip STM32");
  18. LCD_ShowString(30,70,200,16,16,"IIC TEST");
  19. LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  20. LCD_ShowString(30,110,200,16,16,"2015/1/15");
  21. LCD_ShowString(30,130,200,16,16,"KEY1:Write KEY0:Read"); //显示提示信息
  22. while(AT24CXX_Check())//检测不到24c02
  23. {
  24. LCD_ShowString(30,150,200,16,16,"24C02 Check Failed!");
  25. delay_ms(500);
  26. LCD_ShowString(30,150,200,16,16,"Please Check! ");
  27. delay_ms(500);
  28. LED0=!LED0;//DS0闪烁
  29. }
  30. LCD_ShowString(30,150,200,16,16,"24C02 Ready!");
  31. POINT_COLOR=BLUE;//设置字体为蓝色
  32. while(1)
  33. {
  34. key=KEY_Scan(0);
  35. if(key==KEY1_PRES)//KEY_UP按下,写入24C02
  36. {
  37. LCD_Fill(0,170,239,319,WHITE);//清除半屏
  38. LCD_ShowString(30,170,200,16,16,"Start Write 24C02....");
  39. AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
  40. LCD_ShowString(30,170,200,16,16,"24C02 Write Finished!");//提示传送完成
  41. }
  42. if(key==KEY0_PRES)//KEY1按下,读取字符串并显示
  43. {
  44. LCD_ShowString(30,170,200,16,16,"Start Read 24C02.... ");
  45. AT24CXX_Read(0,datatemp,SIZE);
  46. LCD_ShowString(30,170,200,16,16,"The Data Readed Is: ");//提示传送完成
  47. LCD_ShowString(30,190,200,16,16,datatemp);//显示读到的字符串
  48. }
  49. i++;
  50. delay_ms(10);
  51. if(i==20)
  52. {
  53. LED0=!LED0;//提示系统正在运行
  54. i=0;
  55. }
  56. }
  57. }

IIC总结

  1. 进行数据传送时,在SCL为高电平期间,SDA线上电平必须保持稳定,只有SCL为低时,才允许SDA线上电平改变状态。并且每个字节传送时都是高位在前;
  2. 对于应答信号,ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功;
  3. 如果从机需要延迟下一个数据字节开始传送的时间,可以通过把SCL电平拉低并保持来强制主机进入等待状态;
  4. 主机完成一次通信后还想继续占用总线在进行一次通信,而又不释放总线,就要利用重启动信号。它既作为前一次数据传输的结束,又作为后一次传输的开始;
  5. 总线冲突时,按“低电平优先”的仲裁原则,把总线判给在数据线上先发送低电平的主器件;
  6. 在特殊情况下,若需禁止所有发生在I2C总线上的通信,可采用封锁或关闭总线,具体操作为在总线上的任一器件将SCL锁定在低电平即可;
  7. SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。

转载于:https://www.cnblogs.com/CodeWorkerLiMing/p/10830459.html

【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)相关推荐

  1. STM32 IO口模拟ISO7816(PSAM卡)协议

    单片机:stm32f103c8t6   实现方式:纯IO口模拟(RST.I/O.CLK均为普通IO口) 实现功能:接触式CPU卡.PSAM.SIM读(写) 网上有很多相关的代码,有的是用自带的智能卡接 ...

  2. STM32+MAX6675利用io口模拟SPI获取实时温度数据程序及代码

    STM32+MAX6675利用io口模拟SPI获取实时温度数据程序及代码 本文采用的芯片为STM32F103RCT6 温度芯片为MAX6675 因为芯片的spi口只有3个,有部分需要外接W25Q128 ...

  3. STM32 IO口模拟串口通讯

    转自:http://ziye334.blog.163.com/blog/static/224306191201452833850647 前阵子,调项目时需要用到低波特率串口通讯(300的波特率),才发 ...

  4. 使用IO口模拟PWM设计呼吸灯

    <<<<<正文>>>>> <硬件设计> 控制灯的IO口接芯片即可: <软件架构> <软件设计> 我的呼吸 ...

  5. linux下IO口模拟I2C的一些总结

    2019独角兽企业重金招聘Python工程师标准>>> 以前一直在用I2C接口,因为总是有线程的例子就一直没有去深入的了解,今天分析了一下在linux下通用GPIO模拟I2C的程序. ...

  6. 单片机IO口模拟串口程序(发送+接收

    单片机IO口模拟串口程序(发送+接收)[转] qcmc 发表于 - 2011-6-23 0:42:00 前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些 ...

  7. STM8学习笔记----普通IO口模拟串口功能

    串口在产品应用中很常见,但是单片机的默认带的串口往往比较少,有时候就会出现串口不够用,所以就想着能不能用普通IO口模拟串口来实现串口的功能. 要模拟串口首先要清楚串口数据传输过程中的原理. 常用的串口 ...

  8. 串口发送程序linux,单片机IO口模拟串口程序(发送+接收

    前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些现有的资料,基本上完成了.现在将完整的测试程序,以及其中一些需要总结的部分贴出来. 程序硬件平台:11. ...

  9. 基于s32k146的IO口模拟串口

    zhe最近在搞一个IO口模拟LIN的代码,其中包括IO口模拟UART的部分,就记录一下,希望对像我们这样的初学者能有所帮助. 1. 串口协议 串口的特点:全双工,串行,异步 串口协议(我这里选用最常见 ...

最新文章

  1. Nebula3的Input系统
  2. VS2010 安装问题积累
  3. 为什么不能同时用const和static修饰成员函数?
  4. USNews世界大学排名! CS引争议!中国高校霸榜:清华第一,北邮反超CMU
  5. (SenchaTouch+PhoneGap)开发笔记(2)开发环境搭建二
  6. 网络编程中的常见陷阱之 0x十六进制数(C++字面值常量)
  7. Go操作MySql Memache Mongodb
  8. PCB CS架构(工程系统)实现单点登入方法
  9. kvm 网络配置及克隆
  10. 算法(三)、[海量] 数据处理
  11. Node.js与Golang使用感受与小结【二】
  12. Knoll Light Factory 3.2 for Mac 完整汉化版 灯光工厂 for Mac中文版 支持PSCC2019
  13. Windows下解压tar.gz压缩文件
  14. 网络计算机无法访问 没有权限,教您无法访问您可能没有权限使用网络资源怎么解决...
  15. 爱奇艺网络流量分析引擎 QNSM 及其应用
  16. 随机中文姓名 php,PHP生成随机中文姓名 阿星小栈
  17. 视频去声音 免费中文版声音处理软件 轻松教你去除视频声音
  18. fme使用workspacerunner批量处理数据
  19. 生活-啤酒鸡 鸡啤酒 酒啤鸡 啤鸡酒- 做法
  20. C语言常用字符串函数——头文件 <string.h> 到底有什么?

热门文章

  1. Qt ModbusTCP ModbusRTU 使用同步读和异步写
  2. Python 问题--encode、decode及shell中文输出
  3. vim 删除行_【收藏】138条 Vim 命令、操作、快捷键全
  4. Fibonacci数列(数列 取模)
  5. 微信小程序视频弹幕效果
  6. python学习(十七) 扩展python
  7. maven编译项目时提示:cached in the local repository
  8. Shell应用:批量将文件编码由gbk转utf-8
  9. 第二周周四DailyReporting——PM(李忠)
  10. 在Windows XP下,安装VS 2010 Express For Windows Phone .