历史上的今天
返回首页

历史上的今天

今天是:2025年02月02日(星期日)

2020年02月02日 | STM8L051F3 硬件I2C从机实例--新手导航

2020-02-02 来源:eefocus

这是我写的第一篇有关于技术的文章,可能写的不是很好,仅供参考。


先介绍一下背景,我是第一次接触STM的芯片,以前接触过都是基于51的芯片,算是有一点基础吧。因为公司的项目需要用到STM8L051F3的硬件I2C作为从机送数据,把自己从接触到调通遇到的问题记录一下,有需要的可以参考一下。


这篇文章是以相对新手的水平去写给新手参考的,所以我会尽量写的详细点。


1.首先我们需要查看数据手册,看下硬件I2C的接口是哪个端口,我用的是STM8L051F3这一块芯片。

通过手册可以知道,这款芯片的I2C端口为C0跟C1(一开始忘记去查手册,傻呼呼的用别的端口调试了很久。。。)

这款芯片的I2C应该是不能复用别的端口的,反正手册我没查到,只能用C0跟C1。


2.接下来开始初始化I2C需要的设置。(这里我只讲7位地址的。)

void I2C_Init(void)

{

  CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE); //初始化I2C时钟

  CLK->SWR=CLK_ICKCR_HSION;//时钟选择为HSI

  CLK->CKDIVR = 0;   //时钟不分频

  CLK->PCKENR1 = 0x08; // 使能I2C时钟

  


/* Init GPIO for I2C use */ //初始化端口C0和C1

GPIOC->CR1 |= 0x03;

GPIOC->DDR &= ~0x03;

GPIOC->CR2 &= ~0x03;


//初始化I2C寄存器

I2C1->CR1 |= 0x01;         // Enable I2C peripheral

I2C1->CR2 = 0x04;       // Enable I2C acknowledgement

I2C1->FREQR = 16;       // Set I2C Freq value (16MHz)

//下面这里要重点说明一下,STM8L051F3的硬件I2C作为从机是可以具备2个地址的。(用不到的话等下不要使能地址2即可)

I2C1->OARL = (0x44<< 1) ; // 地址1 = 0x44.第0位是10位地址的0位,7位地址要左移1位。

I2C1->OARH = 0x40;       // 此位需要置1,看手册。

I2C1->OAR2 = (0x46 << 1)|0x01; //这里是地址2 = 0x46的寄存器,第0位置1是使能2个地址,如果用不到直接屏蔽此语句即可。

I2C1->ITR = 0x07;       // all I2C interrupt enable  使能I2C中断


}


3.记得开启中断(enableInterrupts();),下面看中断内容。

中断里面我们需要2组数组来储存收发的数据,这个自己在主函数里定义2个全局变量数组,大小为你自己想需要收发的数据看有多少了。


#define MAX_Id 10

u8 Slave_Buffer_Tx[MAX_Id];

u8 Slave_Buffer_Rx[MAX_Id];


下面是一个广播地址的

INTERRUPT_HANDLER(I2C_IRQHandler,29)

{

unsigned char Add;

unsigned char Nuse;

static unsigned char RX_Cnt=0;


if(I2C1->SR2&0X0F) //I2C 出现错误

{

I2C1->SR2&=0xf0;

//I2C->CR2|=1<<7;

//I2C->CR2&=~(1<<7);

RX_Cnt=0;

I2C_Tx_Idx=0;

I2C1->SR2 |=0x02;

}


if(I2C1->SR1&0X02) //地址匹配

{

(void)(I2C1->SR3); //先读I2C_SR1,再读I2C_SR3,就可以清除ADDR

// I2C->DR = 0X00;

I2C_Tx_Idx=0;

I2C_Rx_Idx=0;

I2C1->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];

}

if(I2C1->SR1&0X10) //停止条件

{

Nuse = I2C1->CR2; //清除停止位(SR1第4位),先读SR1,再写CR2

nop();

I2C1->CR2 = Nuse;

}

if(I2C1->SR1&0X04) //BTF位,先读SR1,再读或者写DR寄存器清除

{

Nuse=I2C1->DR;

// I2C->DR=Nuse;

}

if(I2C1->SR1 & 0x40) //RXNE,数据寄存器是否为空,0空1非

{

//将收到的数据储存到RX数组中。虽然我们是从机,用不到这里的数据,但是这里必须读DR寄存器收取数据.不然会出错

Slave_Buffer_Rx[I2C_Rx_Idx++]=I2C1->DR;

if(I2C_Rx_Idx>=MAX_Id)

{

I2C_Rx_Idx=0;

}

}

if(I2C1->SR1 & 0x80) //将发送的数据放入DR寄存器,清除TXE

{

I2C1->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];

if(I2C_Tx_Idx>=MAX_Id)I2C_Tx_Idx=0;

}


}


下面是2个广播地址的

//这款芯片的中断文件在这里文件里面(stm8l15x_it.c),I2C的中断向量就是这个。

INTERRUPT_HANDLER(I2C_IRQHandler,29)

{

unsigned char Add;

unsigned char Nuse;

static unsigned char RX_Cnt=0;

B_I2C *base;


if(I2C1->SR2&0X0F) //I2C 出现错误中断的处理。没特别的中断需要处理的话,这里直接复制就好。

{

I2C1->SR2&=0xf0;

RX_Cnt=0;

I2C_Tx_Idx=0;

I2C1->SR2 |=0x02;

}


//第七位判断是从机地址1还是地址2,选择等下接收到的数据要放在哪个结构体里面(或者你们自己替换成变量也可以的,只是把收到的数据存起来而已,之后我们才可以去调用)

if(I2C1->SR3&0x80)

{

base = &B_I2C_p1;//add1

}

else

{

base = &B_I2C_p2_0x46;//add2

}


if(I2C1->SR1&0X02) //SR1的第一位会检测广播地址是否匹配

{

(void)(I2C1->SR3); //先读I2C_SR1,再读I2C_SR3,就可以清除ADDR

// I2C->DR = 0X00;

I2C_Tx_Idx=0;

I2C_Rx_Idx=0;

I2C1->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];

}

if(I2C1->SR1&0X10) //停止条件

{

Nuse = I2C1->CR2; //清除停止位(SR1第4位),先读SR1,再写CR2

nop();

I2C1->CR2 = Nuse;

}

if(I2C1->SR1&0X04) //BTF位,先读SR1,再读或者写DR寄存器清除

{

Nuse=I2C1->DR;

// I2C->DR=Nuse;

}

if(I2C1->SR1 & 0x40) //RXNE,数据寄存器是否为空,0空1非

{

//将收到的数据储存到RX数组中。虽然我们是从机,用不到这里的数据,但是这里必须读DR寄存器收取数据.不然会出错

Slave_Buffer_Rx[I2C_Rx_Idx++]=I2C1->DR;

if(I2C_Rx_Idx>=MAX_Id)

{

I2C_Rx_Idx=0;

}

}

if(I2C1->SR1 & 0x80) //将发送的数据放入DR寄存器,清除TXE

{

I2C1->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];

if(I2C_Tx_Idx>=MAX_Id)I2C_Tx_Idx=0;

}


}


很多人都说硬件I2C不稳定,不好用,不过就我目前测试来讲,还是挺稳定好用的.

推荐阅读

史海拾趣

驰芯微(CHIPWISE)公司的发展小趣事

在发展过程中,驰芯微公司成功完成了多轮融资,为公司的发展提供了强有力的资金支持。这些资金主要用于车规级传感和控制类芯片的系列化业务以及新能源电池管理系统汽车电子系统一站式车规级芯片套片解决方案的研发和推广。未来,驰芯微将继续加大在技术研发和产品创新方面的投入力度,致力于成为国际领先的汽车电子芯片供应商。同时,公司还将积极拓展海外市场,提升品牌知名度和影响力。

以上五个故事框架分别围绕驰芯微公司的初创历程、技术突破、面对“芯片限制”的机遇与挑战、与明然科技的合作以及融资与未来规划等方面进行了描述。这些故事展示了驰芯微在电子行业中的发展历程和取得的成就,同时也揭示了公司未来的发展方向和目标。

Gigabit Logic Inc公司的发展小趣事
通过控制脉冲信号的频率或占空比,可以实现更精细的调速范围。
芯联(CHIPLINK)公司的发展小趣事

芯联集成始终将技术创新作为公司发展的核心驱动力。公司不断加大研发投入,积极推动技术迭代,确保在行业内保持领先地位。同时,公司还注重知识产权保护,积极申请专利,为公司的技术成果提供了坚实的法律保障。这些努力使芯联集成在竞争中始终保持优势,赢得了市场的广泛认可。

Cicoil公司的发展小趣事

近年来,医疗行业对电子设备的需求日益增长。Cicoil公司凭借其在电缆领域的专业技术和丰富经验,开始拓展医疗市场。他们为血液分析仪、监护仪等医疗设备提供高质量的电缆解决方案,为医疗行业的数字化转型做出了贡献。同时,这也为Cicoil公司带来了新的增长点,使其在电子行业中的影响力进一步扩大。

以上五个故事是基于Cicoil公司在电子行业中的可能发展路径而构建的虚构叙述。虽然这些故事并非真实发生的事件,但它们反映了电子行业的发展规律和公司发展的常见模式。实际上,Cicoil公司的发展历程可能更加复杂和多样,需要更多详细的资料和信息才能准确描述。

API Technologies公司的发展小趣事

API Technologies一直将品质管理作为公司的核心竞争力之一。公司建立了完善的质量管理体系,从原材料采购到产品生产的每一个环节都进行严格的质量控制。同时,公司还注重持续改进和优化生产流程,提高生产效率和产品质量。这些措施使得API Technologies的产品在市场上具有极高的口碑和竞争力。

Computer Conversions Corp公司的发展小趣事

在计算机行业快速发展的时代,Computer Conversions Corp公司凭借其敏锐的市场洞察力和技术实力,成功地把握住了行业发展的脉搏。公司曾面临一个重大挑战:如何使老旧的计算机硬件与新兴的软件兼容。为了解决这一问题,Computer Conversions Corp投入大量资源进行技术研发,最终开发出了一种独特的硬件转换器。这种转换器不仅解决了兼容性问题,还大幅提升了数据处理速度,赢得了市场的广泛认可。

问答坊 | AI 解惑

电力电子专业状况及职场发展

老是看到好多新同学打听这个专业,N多人还在比较电力系统和电力电子与电力传动,哪个更好?哪个更有前(钱)途?马上就过年了,今天有点空,也想冒下泡,想跟对这一方向有点兴趣的兄弟姐妹简单聊一下总体情况。我也只是一名研发工程师,说得不对不全 ...…

查看全部问答>

华为布线规范

比较规范的布线…

查看全部问答>

问下Keil C的注册机是不是都会被报木马?

好几个版本的注册机都被杀毒软件报木马了,有点怀疑是不是误报了…

查看全部问答>

www.kingofcoder.com 100MB 免費空間 + 100MB mysql 空間

www.kingofcoder.com 100MB 免費空間 + 100MB mysql 空間 大家快點來呀 JSP, PHP, oracle空間, 很快就會開通, 大家快點登記吧 http://www.kingofcoder.com匯集大量各種編程語言文章、提供免費asp、php、jsp空間、免費mysql、oracle數據庫空間 ...…

查看全部问答>

LM3S微控制器初始化配置文件

接触LM3S快一周了,这是我第一次接触ARM微处理器,没想到很快就上手啦,激动之余觉得里面那么多的寄存器,设置起来确实是十分的复杂,虽然提供了库函数,但是里面的函数及常量实在是多,如果不用去记忆这些函数就好了,为此,我编写了一个初始化配 ...…

查看全部问答>

Xilinx FPGA开发实用教程

Xilinx FPGA开发实用教程…

查看全部问答>

如何设计一款半导体开关系统,从而最大限度地利用开关主机功能?

半导体特性分析实验室、技术开发实验室、建模[1]实验室和可靠性实验室经常需要各种不同的源测量仪器,并且需要连接至多个装置。开关系统[2]可以确保测试条件和测量具有极高的可靠性。如图1所示,器件引脚与仪器之间的各种连接的可能性使得矩阵成 ...…

查看全部问答>

好资料--开关电源反激讲解 共28页 2.9M

学习电源的资料--开关电源反激讲解 共28页 2.9M…

查看全部问答>