两个STM8S103单片机如何用iic总线故障通讯

STM8 IIC的使用 - STM32/STM8技术论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
STM8 IIC的使用
09:46:46  
11492&查看
STM8单片机价格低廉,而且支持硬件仿真,在一些小型项目中,使用这样的单片机可以降低成本。而且STM8单片机外围电路简单,只需要在VCAPVCAP引脚接一个电容,晶振什么玩意都不需要。
但是不是所有人都能用好这个芯片的,特别是这个芯片的IIC。很多人都说这个地方有问题。故,在这里详细的说明一下STM8的IIC。
为了便于摘录芯片手册内容说理,本文选择一款STM8的具体芯片来描述。
众所周知,单片机与外设进行IIC通信一般有两种方式,一种是IO口模拟出IIC协议,另一种是使用硬件IIC。由于IIC的时序逻辑其实并不复杂,所以很多人喜欢使用IO口模拟IIC,这样操作方便。故我们先介绍IO口模拟出IIC。
如果没使用过STM8的人,一定会觉得,模拟IIC特别简单,对于不同的单片机来说,时序都是一样的,移植不就是操作IO口吗?这有什么好说的呢。那么请各位想一想会怎样操作呢?
答:IIC的SCK线不需要读数据,直接定义为输出。SDA呢,就定义两个宏,一个让SDA脚输出,一个让SDA脚输入,写数据时,让SDA输出,读数据时,让SDA输入。为了能够使用模拟IIC和硬件IIC,所以我们使用硬件IIC那两个脚方便软件编写。
上面这段话,可谓是非常标准的答案了,毫无瑕疵。如果有朋友给我这样的答案,我就面带微笑看着他,让他试。除非运气特别棒,否则,一般是没法成功的。我们来看看这是为什么。
首先,你得在电路上给两个引脚加了上拉电阻。
STM8的引脚是具有推挽输出和上拉输入的,所以很多人为了省事,会直接用引脚连接外部设备,如24C02之类的EEPROM等。
我们看看STM8S003F3P6引脚图,如图:
iic_1.png (98.58 KB, 下载次数: 26)
09:27 上传
STM8这两个引脚标注了T,表示是纯开漏引脚。纯开漏引脚输0时为低,输出1为高阻态,而非高电平。所以,这两个脚不加上拉是无法正常进行通信的。
即时你运气好,加了上拉电阻,也还只是迈出了第一步。
很多人为了切换引脚输入输出会使用类似下面的宏定义:
//IO方向设置
#define IIC_SDA_IN()&&{GPIOB-&DDR&=0XDF;}
#define IIC_SDA_OUT() {GPIOB-&DDR|=0X20;}
iic_2.png (64.73 KB, 下载次数: 19)
09:27 上传
STM8S003F3P6的SDA是PB5,Px_DDR寄存器相应位置1为输出,清0为输入。这样操作是没什么问题的。
但是我们看看STM8对IO控制的两个寄存器,Px_CR1和Px_CR2。
iic_3.png (120.41 KB, 下载次数: 13)
09:27 上传
CR1对真正开漏输出没有影响,我们不用考虑。
iic_4.png (120.83 KB, 下载次数: 27)
09:27 上传
但是CR2这一位影响就大了。如果之前设置输出为1,输出速度为10M。那么在切换为输入模式时,就会将SDA脚的中断使能。而且坑爹的是,STM8S003F3P6中断时按组来弄的,就是所有PB脚进一个中断。而且只要这里开了中断,并且开了全局中断,就算是打开了中断,不用其它操作。
那么现在就酸爽了,每当你要读数据时,引脚就开启中断模式,然后数据位就纷纷触发中断,如果你没有使用PB脚中断,那么只会进入stm8s_it.c中一个空的中断函数,如果你用了,那么恭喜你,整个程序乱七八糟了。
那么究竟正确的方式如何呢?我们来看两个地方:
第一是芯片手册引脚描述:
iic_5.png (30.98 KB, 下载次数: 20)
09:27 上传
iic_6.png (46.41 KB, 下载次数: 16)
09:27 上传
对于PB5脚,就是一个低速脚,所以,初始化的时候,给一个高速根本没有意义。
第二,是IDR寄存器。
iic_7.png (69.8 KB, 下载次数: 22)
09:27 上传
根据这里的描述,发现没?我们只需将SDA脚设置为输出模式就OK,根本不用在读数据时,将引脚切换为输入模式。
所以最后总结一下,STM8使用模拟IIC时,只需将引脚设置为低速输出模式即可。
库函数操作如下:
//初始化IIC
void IIC_Init(void)
{& & & & & & & & & & & &
& & //由于STM8单片机,可以在输入和输出条件下读取IO口状态,故直接设置为输出。
& & GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_SLOW );
& & GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_SLOW );
& & IIC_SCL_H;
& & IIC_SDA_H;
寄存器操作
//初始化IIC
void IIC_Init(void)
{& & & & & & & & & & & &
& & //由于STM8单片机,可以在输入和输出条件下读取IO口状态,故直接设置为输出。
& & GPIOB-&DDR|=0X30;//PB4,PB5设置为输出
& & GPIOB-&CR2&=0XCF;//PB4,PB5设为低速。PB4可也可设置为高速
& & IIC_SCL_H;
& & IIC_SDA_H;
myiic.h文件
#ifndef __MYIIC_H
#define __MYIIC_H
#include &sys.h&
#define IIC_SCL_H& &&&(GPIOB-&ODR |=&&(1 && 4))
#define IIC_SCL_L& &&&(GPIOB-&ODR &= ~(1 && 4))
#define IIC_SDA_H& &&&(GPIOB-&ODR |=&&(1 && 5))
#define IIC_SDA_L& &&&(GPIOB-&ODR &= ~(1 && 5))
#define IIC_SDA_R& &&&((GPIOB-&IDR &&&(1 && 5))&&5)
//IIC所有操作函数
void IIC_Init(void);& && && && && & //初始化IIC的IO口& & & & & & & & & & & & & & & &&&
void IIC_Start(void);& & & & & & & & & & & & & & & & //发送IIC开始信号
void IIC_Stop(void);& & & && && & & & & & & & & & & & //发送IIC停止信号
void IIC_Send_Byte(u8 txd);& & & & & & & & & & & & //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); & & & & & & & & & & & & & & & & //IIC等待ACK信号
void IIC_Ack(void);& & & & & & & & & & & & & & & & & & & & //IIC发送ACK信号
void IIC_NAck(void);& & & & & & & & & & & & & & & & //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);& & & &&&
myiic.c文件
#include &myiic.h&
void delay_us()
& & nop();& & nop();& & nop();& & nop();
//初始化IIC
void IIC_Init(void)
{& & & & & & & & & & & &
& & //由于STM8单片机,可以在输入和输出条件下读取IO口状态,故直接设置为输出。
& & GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_SLOW );
& & GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_SLOW );
& & IIC_SCL_H;
& & IIC_SDA_H;
//产生IIC起始信号
void IIC_Start(void)
& & IIC_SDA_H;& & & && && & & && &
& & IIC_SCL_H;
& & delay_us();
& & IIC_SDA_L; //START:when CLK is high,DATA change form high to low
& & delay_us();
& & IIC_SCL_L; //钳住I2C总线,准备发送或接收数据
//产生IIC停止信号
void IIC_Stop(void)
& & IIC_SCL_L;
& & IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
& & delay_us();
& & IIC_SCL_H;
& & IIC_SDA_H;//发送I2C总线结束信号
& & delay_us();& & & & & & & & & & & & & & & & & & & & & & & & & & & && & & & & &
//等待应答信号到来
//返回值:1,接收应答失败
//& && &&&0,接收应答成功
u8 IIC_Wait_Ack(void)
& & u8 ucErrTime=0;
& & IIC_SDA_H;nop();& & & && &
& & IIC_SCL_H;nop();
& & while(IIC_SDA_R)
& && &&&ucErrTime++;
& && &&&if(ucErrTime&250)
& && && && &IIC_Stop();
& && && && &return 1;
& & IIC_SCL_L;//时钟输出0 & & & && &
& & return 0;&&
//产生ACK应答
void IIC_Ack(void)
& & IIC_SCL_L;
& & IIC_SDA_L;
& & delay_us();
& & IIC_SCL_H;
& & delay_us();
& & IIC_SCL_L;
//不产生ACK应答& & & & & & & && &&&
void IIC_NAck(void)
& & IIC_SCL_L;
& & IIC_SDA_H;
& & delay_us();
& & IIC_SCL_H;
& & delay_us();
& & IIC_SCL_L;
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答& & & & & & & & & & & && &
void IIC_Send_Byte(u8 txd)
{& && && && && && && && &
& & u8& && &
& & IIC_SCL_L;//拉低时钟开始数据传输
& & for(t=0;t&8;t++)
& & {& && && && &&&
& && &&&if((txd&0x80)&&7)
& && && && &IIC_SDA_H;
& && &&&else
& && && && &IIC_SDA_L;
& && &&&txd&&=1; & & & && &
& && &&&delay_us();& &//对TEA5767这三个延时都是必须的
& && &&&IIC_SCL_H;
& && &&&delay_us();
& && &&&IIC_SCL_L;& & & &
& && &&&delay_us();
& & }& & & &&&
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK& &
u8 IIC_Read_Byte(unsigned char ack)
& &&&unsigned char i,receive=0;
& &&&for(i=0;i&8;i++ )
& && &&&IIC_SCL_L;
& && &&&delay_us();
& && &&&IIC_SCL_H;
& && &&&receive&&=1;
& && &&&if(IIC_SDA_R)receive++;& &
& && &&&nop();
& & }& & & & & & & & & & & & & & & & & & & &&&
& & if (!ack)
& && &&&IIC_NAck();//发送nACK
& && &&&IIC_Ack(); //发送ACK& &
00:13:06  
调了一整天的iic终于调通了,楼主的程序可以用,我的模拟iic程序在stm32上可以用,stm8死活不行,现在终于好了,非常感谢,强调一点stm8s模拟iic不用改变SDA引脚的输入输出方向。
16:16:07  
目测这代码是可以的
可是 调DS3231 就是调不通,&&读不到数据,&&不知哪里问题了
10:27:04  
讲的简介明了& &虽都是基础知识&&但却是很有用的
17:14:01  
高级工程师
09:56:32  
10:42:08  
感谢楼主分享!学习
02:00:01  
08:48:40  
真的是非常感谢,这些自己还真没注意,刚好要调iic程序,感觉少花很多时间。
08:56:31  
不错,谢谢楼主分享
16:49:01  
感谢分享!不过我在调试时出现 读取16位数据 高8位正确 低8位不存在的情况(全0),检查发现 在写入函数中(写入16位数据),低8位的数据根本没写进去,这是什么原因呢? 现在用的是 stm8s003f3p6, 之前用STM32f103开发板调试,数据都是正常的。
下面是我读写函数:
void LDC1612_WriteDATA(u8 addr,u16 dt)
& & & && &IIC_Start();
& & & && &delay_us();
& & & & IIC_Send_Byte(0x54); //发送总线地址
& & & & IIC_Wait_Ack();
& & & & IIC_Send_Byte(addr);&&//发送从机寄存器地址
& & & & IIC_Wait_Ack();
& & & & IIC_Send_Byte(dt&&8);
& & & & IIC_Wait_Ack();
& & & & IIC_Send_Byte(dt);
& & & & IIC_Wait_Ack();
& & & & IIC_Stop();
& & & & delay_us();
u16 LDC1612_ReadDATA(u8 addr)
& & & & u16 temp=0;
& & & & IIC_Start();
& & & & IIC_Send_Byte(0x54);
& & & & IIC_Wait_Ack();
& & & & IIC_Send_Byte(addr);&&//发送从机地址
& & & & IIC_Wait_Ack();
& & & & delay_us();
& & & & IIC_Start();
& & & & IIC_Send_Byte(0x55);
& & & & IIC_Wait_Ack();
& & & & temp=IIC_Read_Byte(1); //&&0&&代表 NACK
& & & & IIC_Ack();
& & & & temp=(temp&&8)|IIC_Read_Byte(0);
& & & & IIC_NAck();
& & & & IIC_Stop();
& & & && & & &
17:03:13  
为啥我使用楼主的代码IIC的读写不能成功呢?
14:10:08  
11楼的帅哥我也遇到和你同样的问题了 请问一下你的是怎么解决的 谢谢您了
20:43:25  
感谢分享!不过我在调试时出现 读取16位数据 高8位正确 低8位不存在的情况(全0),检查发现 在写入函数中(写入16位数据),低8位的数据根本没写进去,这是什么原因呢? 现在用的是 stm8s003f3p6, 之前用STM32f103开发板调试,数据都是正常的。
下面是我读写函数:
void LDC1612_WriteDATA(u8 addr,u16 dt)
接受函数中已经包含ACK了,你仔细看看
15:02:03  
16:21:30  
看一看&&瞧一瞧
工程师职场
Powered by
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司51单片机IIC总线通信不会,谁给讲讲? - 单片机/MCU论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
51单片机IIC总线通信不会,谁给讲讲?
助理工程师
09:07:16  
串口和1602都会了,但是这个不会。。。。。。红外通信要用这个。。。。
高级工程师
09:37:54  
网上都有的例子,只要修改相应的端口就可以了
助理工程师
09:40:39  
网上都有例子,有单片机IO口模拟的。有的单片机带硬件IIC,就更方便了还稳定。
助理工程师
23:10:13  
现在还没学会。。。。。。
Powered by
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司2个stm8的单片机如何进行iic通讯
本回答由提问者推荐
var sogou_ad_id=731547;
var sogou_ad_height=160;
var sogou_ad_width=690;您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
(单片机)数字接收机设计生产实习综述.docx 21页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
你可能关注的文档:
··········
··········
哈尔滨理工大学认识实习姓名:谷允捷班级:通信13-1
评阅教师:成绩:说明:2016年 1月 8日内容:识实习具体内容:使用STM8单片机系统设计一款可调式数字收音机,指定应用芯片为STM8S103和RDA5807,要求使用按键进行电台频率搜索,指定频率进行播放调频广播内容,使用数码管显示当前调频频率,并能进行音量控制。成绩标准:
1.优秀:(1)报告完整清晰。(2)实验基本功能完成良好,并且增加两个以上模块的功能,运行正确。(3)答辩考核回答基本正确。
2.良好:(1)报告基本完整。(2)实验基本功能完成,并能够增加部分功能。(3)答辩考核回答部分正确。
3.中、及格:(1)报告基本完整。(2)实验部分功能完成。(3)答辩考核回答部分正确。
4.不及格:(1)多次无假条缺勤。(2)无报告,不参加考核。(3)报告及实验演示效果严重雷同。(4)实验无现象。(5)答辩考核不合格。实习要求实习目的使用STM8单片机系统设计一款可调式数字收音机,指定应用芯片为STM8S103和RDA5807,要求使用按键进行电台频率搜索,指定频率进行播放调频广播内容,使用数码管显示当前调频频率,并能进行音量控制。实习内容本次实习要求使用配发STM8单片机实现数字接收机功能,使是收音机能接收到一定频率信号,并且在答辩调试过程中不能出现差错,要求收台清晰,不得出现自动跳台,声音混杂程度过高等现象。调整音量时,要能实现从1——15音量连续跳变,不得出现漏掉音量以及不受控制就使音量跳变等情况,将课堂上学到的理论知识与实际应用结合起来,对电子电路、电子元器件、印制电路板等方面的知识进一步加深认识,同时在软件编程、排错调试、相关仪器设备的使用技能等方面得到较全面的锻炼和提高。实习要求实现实习要求,做出调频收音机了解IIC协议的书写方式掌握本次实习的所需要的部分硬件电路,及其在整体电路中所起的作用。充分了解本次实习所用到的程序,了解每一部分的作用分析程序流程,画出主程序,子程序的流程图了解每一部分应用实现按键的充分利用,在没有使用的按键上添加可以使用的成分,以实现电路的实习器材stm8单片机:提供硬件电路与各种器材PC:用于下载程序ST-LINK:用于连接PC 和学习板,将编码程序下载到单片机中。电源线:用于给单片机学习板上电,电压为5V。耳机:用于接收机输出放音橡胶按键:因为单片机上的键盘为电容键盘,所以我们要借助橡胶按键控制直流电机:用于对本次实习的扩展三.关键程序分析#include&iostm8s103k3.h&
//头文件#include&TM1628.h&//1628
//控制数码管芯片#define u8 unsigned char
//宏定义#define u16 unsigned int
//宏定义#define u32 unsigned long
//宏定义u16table1[10]={0xeb,0x28,0xb3,0xba,0x78,0xda,0xdb,0xa8,0xfb,0xfa};
//数码管显示地址不带小数点数组u16 table2[10]={0xef,0x2c,0xb7,0xbe,0x7c,0xde,0xdf,0xac,0xff,0xfe}; //数码管显示数据带小数点数组unsigned int tempp=0;unsigned int flag=0;int main(){
unsigned int temp=0x9088;//起作用的是最后一位将初始音量设置为8
unsigned int r_ //定义存储按键位置的变量
//定义储存声音字符的变量
unsigned int shang1,shang2,shang3; //定义数码管字符变量
unsigned char yu1,yu2,yu3;//定义用于储存余数的变量
Clk_Config();
//时钟初始化函数
TM_init();
//TM1628初始化设置函数
radio_init();
//radio初始化设置函数TM_w_command(0x03);
//设置显示模式,7位10段模式,这是对数码管的设置
TM_w_command(0x44);//设置固定地址模式,写数据到寄存器
while(1) //此语句在函数运行的过程中一直在执行,不断重复扫描
r_key=TM_r_k
正在加载中,请稍后...

我要回帖

更多关于 iic总线规范 的文章

 

随机推荐