总结stm8硬件IIC主模式的寄存器设置及调试心得

发布者:之敖赵先生最新更新时间:2019-04-02 来源: eefocus关键字:stm8  硬件IIC  主模式  寄存器设置 手机看文章 扫描二维码
随时随地手机看文章

一、开发环境


开发软件:STVD


芯片型号:stm8s103


硬件接口:I2C(主模式)


二、寄存器主要用到的功能(按用户手册的顺序)


1. I2C_CR1(控制寄存器1):


(1)bit0:控制I2C模块的启动/禁用。此功能主要用于I2C总线初始化的时候,配置TRISER相关寄存器功能的时候必须先禁用I2C模块才可以进行写操作。


2. I2C_CR2(控制寄存器2)


(1)bit7:设置1实现软复位I2C模块。当I2C总线始终处于繁忙状态的时候通过复位实现恢复。


(2)bit3:设置ACK应答的位置。在I2C总线初始化的时候配置,通常是作清零操作,用于表示ACK位控制被移位寄存器正在接收的这个当前字节的应答或者不应答。


(3)bit2:设置ACK应答使能。这个位需要根据协议决定是否需要使能ACK,并在I2C主机每读取来自从机的一字节数据之前进行设置,这样硬件II2C就会自动在读取到数据后作出对应的ACK响应。实际上这个ACK应答是始终存在的,如果该位为0,表示当前应答位为NACK,许多I2C设备在读取最后一个字节的数据的时候会要求主机回复的是NACK,其实就是把该位设置为0即可。


(4)bit1:设置该位用于产生停止位。用于释放总线,也就是总线恢复闲置状态。


(5)bit0:设置该位用于产生起始位。产生起始位后,进入主模式。


3. I2C_FREQR(频率寄存器)


(1)bit5~0:设置外设时钟的频率。有效的取值范围0b000001~0b110010表示1MHz~50MHz。在I2C总线初始化的时候配置;如果用内部晶振,数值设置为16即可表示外设时钟的频率是16MHz;如果用的是外部晶振,根据外部晶振的时钟频率设置对应的数值即可。


4. I2C_OARL(自身地址寄存器LSB)


(1)bit7~1:设置主机在I2C总线上自身的地址(地址的第7:1位)。


(2)bit0:设置主机在I2C总线上的自身地址(地址的第0位,在地址位数为10的时候有效)




5. I2C_OARH(自身地址寄存器MSB)


(1)bit2~1:设置主机在I2C总线上的自身地址(地址的第9:8位,在地址位数为10的时候有效)




6. I2C_DR(数据寄存器)


(1)bit7~0:用于存放接收到的数据或放置用于发送到总线的数据。这个寄存器的用法很简单,主机需要往从机写数据的时候把数据按字节写入此寄存器即可,主机需要往从机读数据的时候把这个寄存器内的数据读取并写入变量中即可。




7. I2C_SR1(状态寄存器1)


(1)bit7:通过判断该位可以知道写入I2C_DR的数据是否已经全部发送出去,从而决定是否开始发送下一个字节的数据。


(2)bit6:通过判断该位可以知道是否接受到来自从机的数据,该位被置位的状态下,从I2C_DR中读取数据才是有意义的。


(3)bit1:通过判断该位可以知道需要与主机进行通讯的从机地址是否已经发送。


(4)bit0:通过判断该位可以知道起始位是否已经发送。




8. I2C_SR2(状态寄存器2):目前开发过程中没有用到该寄存器。




9. I2C_SR3(状态寄存器3):目前开发过程中没有用到该寄存器。




10. I2C_ITR(中断寄存器):如果开发时希望特定事件以中断形式通知,可以通过该寄存器来实现。比如,写入一字节数据至I2C_DR寄存器后,CPU处理其它事件,当收到TXE触发的中断事件后,再写下一字节数据。这样CPU在处理整个I2C读写事件的过程中可以不需要进行循环判断等待。




11. I2C_CCRL(时钟控制寄存器低位部分),I2C_CCRH(时钟控制寄存器高位部分)


(1)这两个寄存器在I2C总线初始化的时候进行配置,需要注意的是这两个寄存器需要在I2C模块禁用的状态下改变值。


(2)I2C_CCRH的bit7:如果I2C通讯速度小于等于标准速度(100KHz),该位置0;如果I2C通讯速度大于标准速度,则该位置1表示是快速模式(比较常用的是400kHz)


(3)I2C_CCRL的bit6:表示快速模式下的占空比,即I2C总线的SCL时钟信号的低电平时间(t_low)与高电平时间(t_high)的比值。t_low+t_high就是一个SCL时钟信号脉冲周期的长度,i2c总线的通讯速度f_scl = 1/(t_low+t_high)。假如单片机采用16MHz的外部晶振且I2C通讯速度是400KHz的情况下,


(4)I2C_CCRH的bit3:0以及I2C_CCRL的bit7~0共12个bit表示CCR的值。CCR的具体计算方式举个例子大致描述一下:假如单片机采用16MHz的外部晶振(即t_ck=16)且I2C通讯速度是400KHz的情况下,此时采用占空比为16:9(I2C_CCRL的bit6设置为1),则CCR=(t_ck)/[1/(t_low+t_high)*(25)]=(16*1000000)/(400000*25)= 1




12. I2C_TRISE(TRISE寄存器)


(1)bit5~0:在快速/标准模式下的大上升时间(主模式)。这个时间需要根据从机的特性需求来设置。


标准模式(100KHz)下的计算公式:(1000ns / t_pclk1 + 1) ns; t_pclk1为从机的最大上升时间


快速模式(400KHz)下的计算公式:(300ns / t_pclk1 + 1)ns




三、调试心得


1. 如果外设时钟的频率小于10MHz,建议在标准模式(100KHz通讯速度)下进行开发调试。


2. 发送从机地址时(7-bit),需要加上1bit读写位(0为写,1为读),拼成一整个字节进行发送。


3. 发送完地址+读写字节后,必须对I2C_SR3寄存器进行读操作,实现清状态寄存器,否则总线会堵死。


4. 读取数据前需设置ACK应答,如果需要NACK则设置ACK应答位为0(示例函数中ACK设置为0,需根据协议需求进行修改)




四、读写函数代码


1. 主机往从机读一个字节数据:


#define I2C_OVER_TIME   0xFA  // 超时处理时间需要根据晶振频率调整

#define SLAVE_ADDR_WR   0x20  // 7-bit从机地址 + 1-bit写信号

#define SLAVE_ADDR_RD   0x21  // 7-bit从机地址 + 1-bit读信号

u8 I2C_Read_Byte(u8 reg, u8 *pdata)

{

u16 cnt = 0;


    /* Generate start & wait event detection */

    I2C->CR2 |= 0x01; 

while (!(I2C->SR1 & 0x01))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02; 

return 1;

}

}


cnt = 0;

/* Send slave Address in write direction & wait detection event */

    I2C->DR = SLAVE_ADDR_WR;

while (!(I2C->SR1 & 0x02))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02;  

return 1;

}

}

    I2C->SR3;


cnt = 0;

/* Send register to be read */

I2C->DR = reg; 

    while(!(I2C->SR1 & 0x80))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02; 

return 1;

}

}

    

    cnt = 0;

/* Generate start & wait event detection */

    I2C->CR2 |= 0x01; 

while (!(I2C->SR1 & 0x01))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02; 

return 1;

}

}


cnt = 0;

/* Send register to be read */

I2C->DR = SLAVE_ADDR_RD; 

    while(!(I2C->SR1 & 0x02))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02;  

return 1;

}

}

I2C->SR3;


cnt = 0;

I2C->CR2 &= ~0x04; //nack 

/* waiting for byte from slave */

while (!(I2C->SR1 & 0x40))

{

if ( ++cnt > I2C_OVER_TIME )

{

/* Generate stop signal */

    I2C->CR2 |= 0x02; 

return 1;

}

}

    *pdata = (u8)(I2C_ReceiveData());


    /* Generate stop signal */

    I2C->CR2 |= 0x02; 


return 0;

}


2. 主机往从机写一字节数据:

u8 I2C_Write_Byte(u8 reg,u8 data)  

u16 cnt = 0;


/* Generate start & wait event detection */

I2C->CR2 |= 0x01;

while (!(I2C->SR1 & 0x01))

{

if ( ++cnt > I2C_OVER_TIME )

{

I2C_GenerateSTOP(ENABLE); 

return 1;

}

}


cnt = 0;

/* Send slave Address in WRITE direction & wait detection event */

I2C->DR = SLAVE_ADDR_WR;

while (!(I2C->SR1 & 0x02))

{

if ( ++cnt > I2C_OVER_TIME )

{

I2C_GenerateSTOP(ENABLE);

return 1;

}

}

I2C->SR3;


cnt = 0;

/* Send internal register address to write */

I2C->DR = reg;

while(!(I2C->SR1 & 0x80))

{

if ( ++cnt > I2C_OVER_TIME )

{

I2C_GenerateSTOP(ENABLE);

return 1;

}

}


cnt = 0;

/* Send Data to write */

I2C->DR = data;

while (!(I2C->SR1 & 0x80))

{

if ( ++cnt > I2C_OVER_TIME )

{

I2C_GenerateSTOP(ENABLE);

return 1;

}

}

 

    I2C_GenerateSTOP(ENABLE); 


return 0;

}



关键字:stm8  硬件IIC  主模式  寄存器设置 引用地址:总结stm8硬件IIC主模式的寄存器设置及调试心得

上一篇:stm8 IAR 编译错误Fatal Error[Cp001]
下一篇:STM8L051的硬件I2C调试

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

STM8开发环境搭建(STVD + COSMIC)
一、STM8开发IDE 1. STVD + COSMIC ST Visual Develop (STVD)只支持汇编开发,C语言开发需要再安装COSMIC,配套起来使用。 2. IAR IAR也可以用来开发STM8 下面介绍STVD + COSMIC的搭建方式 二、环境搭建 1. STVD下载、安装 直接从官网下载: https://www.st.com/en/development-tools/stvd-stm8.html 安装很简单,基本下一步往下点。 2. COSMIC下载、安装 对于stm8可以使用32K免费使用权限,每台电脑是1年,以及16K的限制权限,需要使用邮件获取license.lic文件。 下载
[单片机]
<font color='red'>STM8</font>开发环境搭建(STVD + COSMIC)
STM8与汇编语言(12)--EEPROM应用
在单片机的应用系统中,经常会用到EEPROM,用来保存一些掉电后仍然需要保存的数据。传统的方法是在单片机外再加一个EEPROM芯片,这种方法除了增加成本外,也降低了可靠性。现在,许多单片机芯片公司也都推出了集成有小容量EEPROM的单片机,降低了成本,提高了可靠性。 STM8单片机芯片内部也集成有EEPROM,容量从640字节到2K字节。最为关键的是,在STM8单片机中,访问EEPROM就向访问常规的内存一样,非常方便。EEPROM的地址空间与内存是统一编址的,地址从004000H开始,大小根据不同的芯片型号而定。 如果我们要读出EEPROM中的第一个单元的内容,则只要执行LD A,$4000这条指令,就可以将EEPROM
[单片机]
STM8 开发故事--之蜂鸣器 BEEP设计坑爹的引脚(一)
为什么选stm? 最近才又开始搞stm8开发。虽然以前从来没用过stm的产品,但是stm在嵌入界鼎鼎大名可是早有耳闻。据某IC供应商提供的数据当今(2019年)56%的MCU都是stm的。要说为什么这么火,最直接的原因:便宜而且功能强大。淘宝上stm8s的最小系统板才1块多RMB。 因为要要开发的产品要用液晶显示数字,而且是用电池供电。所以选择了stm8L052c6t6。有朋友推荐我用华大的HC32L136。本想支持国行的,但是供应商不跟进就涮了,还有一个原因又怕资料太少,还是暂时放弃了。我以前做过51的项目,同样的51atmel的质量就好过华邦,华邦掉程序的概率要高很多。这也是我选stm的原因。于是在tb买了一块带液晶显示的
[单片机]
<font color='red'>STM8</font> 开发故事--之蜂鸣器 BEEP设计坑爹的引脚(一)
IAR+STM8——TIM1定时溢出中断
STM8的TIM1是16位高级控制定时器,作为新手不要急着玩高级功能,先从简单的定时溢出中断开始。那么这个简单的目标就定为LED1亮500ms,灭500ms,循环往复,如此而已。 #i nclude iostm8s207sb.h #define LED1_FLASH PD_ODR_ODR3 = !PD_ODR_ODR3 // 开发板上的LED1接在PD3上 void CLK_init(void) { CLK_CKDIVR = 0x08; // 16M内部RC经2分频后系统时钟为8M } void GPIO_init(void) { PD_DDR = 0x08; // 配置PD端口的方向寄存器PD3输出 PD_CR1 = 0x
[单片机]
STM8 LIN主模式
STM8 LIN模式功能描述 在LIN模式下,LIN标准要求的数据格式是8位数据位加1位停止位。 完成这样的设置需要将UART_CR1的M位清0,同时把UART_CR3的STOP 位也清0。 主模式 UART初始化 步骤: 1.设置UART_BRR2和UART_BRR1来选择期望的波特率。 2.将UART_CR3的LINEN位置1来使能LIN模式。 3.将UART_CR2的TEN位和REN位置1来使能发送器和接收器。 LIN报文头(header)的发送 按照LIN协议,所有在LIN总线上的通讯都由主设备通过发送报文头(header)发起,报文头之后是响应。报文头由主任务(主节点)发送,而数据由节点(主节点或者从节点)的从任务
[单片机]
<font color='red'>STM8</font> LIN<font color='red'>主模式</font>
stm8及DS1302的一些操作
最近想看下DS1302内部RAM掉电后的状态,会是默认的全0x00么? 首先查阅网上的资料和芯片相关手册,并没有对它的介绍,DS1302是块很普通的时钟芯片,之前用别的单片机也操作过,但从来没有留意这点。决定操作下1302,看下RAM究竟是什么状态。 手头别的什么单片机都没有,就有块上次代理商留下的stm8L15X系列单片机demo板。那就用这块单片机试下吧。 首先配置系统时钟,在stm8的库文件(STM8S_StdPeriph_Lib_V2.1.0)里有相关的函数获取相关时钟状态,如下: SysClkFreq = CLK_GetClockFreq(); SysClkSource = CLK_GetSYSCLK
[单片机]
基于STM8系列8位通用MCU的电容式触摸感应方案
1引言 相较于机械式按键和电阻式触摸按键,电容式触摸按键不仅耐用,造价低廉,机构简单易于安装,防水防污,而且还能提供如滚轮、滑动条的功能。但是电容式触摸按键也存在很多的问题,因为没有机械构造,所有的检测都是电量的微小变化,所以对各种干扰敏感得多。ST 针对家电应用特别是电磁炉应用,推出了一个基于 STM8 系列 8 位通用微控制器平台的电容式触摸感应方案,无需增加专用触摸芯片,仅用简单的外围电路即可实现电容式触摸感应功能,方便客户二次开发。 2 方案介绍 ST 的电容式触摸按键方案通过一个电阻和感应电极的电容 CX 构成的阻容网络的充电 / 放电时间来检测人体触摸所带来的电容变化。如图 1 所示,当人手按下时相当于感应电极上并
[单片机]
基于<font color='red'>STM8</font>系列8位通用MCU的电容式触摸感应方案
STM8-按键切换灯的亮灭
目的:熟悉按位读入语句GPIO_ReadInputPin(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin);的使用 #include stm8s.h #define ulong unsigned long void delay(ulong i) { while(i--); }//延时函数 void main(void)////////////主函数 { unsigned char flag=0; GPIO_DeInit(GPIOD); GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_De
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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