概述
我下面要说的是基于stm32单片机的模拟IIC时序,以及是一些要注意的事项;结合自己所做的MMA7455加速度传感器,我把模拟IIC的源代码贴了出来,大家可以参考一下。
2.注意开始信号,停止信号,响应信号,非响应信号的时序,特别是要留意高低电平时间的延时:
3.应答信号分为主机应答和从机应答:
主机应答是在主机从从机中读取数据时每次读取完一个字节的数据后主机给从机的一个应答信号,表示主机已收到数据了。
从机应答是指主机给从机发送数据时从机给主机的应答,给一个应答就代表从机已经收到了数据,为主机接下来的工作做个判断。主机在核查从机的应答信号的时候,必须先将SDA总线拉高,释放总线。
非应答信号是主机给从机的,当读取完一字节数据以后,主机不再去读取数据就给从机一个非应答信号,接着一个停止信号,直接给停止信号也是可以结束此次读操作,但是会对后面的操作带来影响。
主机发送一个字节的数据,从高位开始发送。SCL位高电平的时候,数据必须保持稳定,所以可以在SCL为低电平时组织数据;同理读取数据也是类似的。
4.SCL是单向的,由master控制。SDA是双向的,master可以控制,slaver也可以控制。
主机给从机写入数据时,SDA在SCL低电平的时候变化,SDA在SCL高电平的时候保持不变,也就是说在SCL上升沿时写入数据。
主机从从机读取数据时,SDA在SCL高电平的时候变化,SDA在SCL低电平的时候保持不变,也就是说在SCL下升沿时读出数据。
需要注意的是:写入数据时就是要先改变SDA的值再去制造一个SCL的上升沿,读取数据时就是要先改变SDA的值再去制造一个SCL的下降沿,先后顺序必须把握好。
下面是我在用MMA7455加速度传感器时,写的IIC时序;程序已验证过可使用,大家可以参考一下
C Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
#define
mma7455addree 0x3a //每个设备有还会有自己的设备地址
#define sdah GPIO_SetBits(GPIOA,GPIO_Pin_0)
#define sclh GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define sdal GPIO_ResetBits(GPIOA,GPIO_Pin_0)
#define
scll GPIO_ResetBits(GPIOA,GPIO_Pin_1)
void sdain() { GPIO_InitTypeDef i2csdain; i2csdain.GPIO_Pin = GPIO_Pin_0; i2csdain.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置为浮空输入 GPIO_Init(GPIOA, &i2csdain); } void sdaout() { GPIO_InitTypeDef i2csdaout; i2csdaout.GPIO_Pin = GPIO_Pin_0; i2csdaout.GPIO_Mode = GPIO_Mode_Out_PP; i2csdaout.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &i2csdaout); } void sclout() { GPIO_InitTypeDef i2csclout; SystemInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); i2csclout.GPIO_Pin = GPIO_Pin_1; i2csclout.GPIO_Mode = GPIO_Mode_Out_PP; i2csclout.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &i2csclout); } void i2cst() //启动信号的函数 { sdaout(); sclh; sdah; Delay_us( 10 ); sdal; Delay_us( 5 ); scll; } void i2ced() //停止信号的函数 { sdaout(); sdal; sclh; Delay_us( 10 ); sdah; Delay_us( 5 ); } void i2cack() //等待信号,当发送器发送一个数据之后,需要等待从接收端发过来的应答信号,主机等待从机应答 { unsigned char i; sdain(); sclh; Delay_us( 5 ); while ((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1 ) && (i < 250 )) i++; //检测到SDA为低,也就是从机产生了应答信号或者 从机没有应答信号,导致 超时,都会跳出该函数。
scll;
Delay_us( 10 ); } void i2cwrda( unsigned char da) //写入一个字节的函数 { unsigned char i, temp, temp1; sdaout(); scll; temp1 = da; for (i = 0 ; i < 8 ; i++) { scll; temp = temp1; temp = temp & 0x80; if (temp == 0x80) { sdah; } else { sdal; } Delay_us( 15 ); sclh; Delay_us( 15 ); temp1 = temp1 << 1 ; } }
unsigned
char
i2creda()
//读取
一个字节的函数
{ unsigned char i, j; sdain(); for (i = 0 ; i < 8 ; i++) { sclh; Delay_us( 5 ); j = (j << 1 ) | GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); scll; Delay_us( 5 ); } return j; } void mma7455Write( unsigned char addr, unsigned char dat) //往 mma7455的addr地址写入addr数据
{ i2cst(); i2cwrda(0x3a); i2cack(); i2cwrda(addr); i2cack(); i2cwrda(dat); i2cack(); i2ced(); } unsigned char mma7455 Read( unsigned char addr) //读取mma7455的addr地址的数据 { unsigned char num1; i2cst(); i2cwrda(0x3a); i2cack(); i2cwrda(addr); i2cack(); i2cst(); i2cwrda(0x3b); i2cack(); num1 = i2creda(); i2ced(); return (num1); } |
其实多机通信可以用一个简单的办法解决,只要在只要在上面mma7455Write,mma7455Read函数中用if语句根据不同的标志位选择相应的设备地址,要读取地址即可。大家可以去试一下!
这是我个人的一些总结,有什么不对的望指正!大家一起进步!
最后
以上就是落后胡萝卜为你收集整理的基于stm32单片机的模拟IIC时序(附源码)的全部内容,希望文章能够帮你解决基于stm32单片机的模拟IIC时序(附源码)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复