STM8S GPIO模拟I2C的底层代码

发布者:SparklingSoul最新更新时间:2021-09-26 来源: eefocus关键字:STM8S  GPIO  模拟I2C 手机看文章 扫描二维码
随时随地手机看文章

底层代码

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。


GPIO初始化设置

这颗STM8S上,具有真·开漏功能的引脚是PB4和PB5,这两个引脚也正是片上I2C外设的默认引脚。端口设置如下:


PB4 :I2C的SCL时钟线,开漏输出模式

PB5 :I2C的SDA数据线,开漏输出模式

SCL和SDA初始化时,推荐选用高阻态输出

/**

  * @brief  I2C端口初始化

  * @param  None

  * @retval None

  */

void I2C_GPIO_Init(void)

{

  GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);

  GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);

  I2C_SDA_OUT(1);

  I2C_SCL_OUT(1);

}


I2C主机向从机发送一个字节,都会等待从机通过SDA线返回一个“已接收(ACK)”指令。此时主机的SDA应设置为输入,而在其他环节中应该保持开漏输出。而根据不同从机的I2C时序,有时也需要将SCL设置为输入。

/**

  * @brief  SDA设为输出

  * @param  None

  * @retval None

  */

void I2C_SDA_SET_OUTPUT(void)

{

  GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);

}


/**

  * @brief  SCL设为输出

  * @param  None

  * @retval None

  */

void I2C_SCL_SET_OUTPUT(void)

{

  GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);

}


/**

  * @brief  SDA设为输入

  * @param  None

  * @retval None

  */

void I2C_SDA_SET_INPUT(void)

{

  GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_IN_FL_NO_IT);

}


/**

  * @brief  SCL设为输入

  * @param  None

  * @retval None

  */

void I2C_SCL_SET_INPUT(void)

{

  GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_IN_FL_NO_IT);

}


GPIO输入检测

既然有了SDA或SCL的输入设置,自然需要有判断输入值的函数。


/**

  * @brief  SDA输入电平检测

  * @param  None

  * @retval 1=输入为高电平  0=输入为低电平

  */

unsigned char I2C_SDA_IN(void)

{

  return (!!GPIO_ReadInputPin(I2C_PORT, I2C_SDA_PIN));

}


/**

  * @brief  SCL输入电平检测

  * @param  None

  * @retval 1=输入为高电平  0=输入为低电平

  */

unsigned char I2C_SCL_IN(void)

{

  return (!!GPIO_ReadInputPin(I2C_PORT, I2C_SCL_PIN));

}


模拟I2C代码

包括:


起始条件,结束条件

回从机ACK,回从机NACK: 用于主机从从机读1字节(此时主从的身份对调)后,还要向其发送请继续(ACK) 或 请停下(NACK) 信号

等待从机回ACK: 主机向从机发送1字节后,需要等待从机返回接收到(ACK) ,如果接收到的是 接收到(ACK)

从从机读1字节: 完成读1字节后,需要向从机发送请继续(ACK) 或 请停下(NACK) 信号

向从机写1细节: 完成写1字节后,需要等待从机返回接收到(ACK) 信号。

起始条件,结束条件

/**

  * @brief  I2C传输开始

  * @param  None

  * @retval None

  */

void I2C_START(void)

{

  I2C_SDA_SET_OUTPUT();

  

  I2C_SDA_OUT(1);

  I2C_SCL_OUT(1);

  Delay_1us(10);/

  I2C_SDA_OUT(0);

  Delay_1us(10);

  I2C_SCL_OUT(0);

  Delay_1us(10);

}


/**

  * @brief  I2C传输结束

  * @param  None

  * @retval None

  */

void I2C_STOP(void)

{

  I2C_SDA_SET_OUTPUT();

  

  I2C_SDA_OUT(0);

  I2C_SCL_OUT(0);

  Delay_1us(10);//

  I2C_SCL_OUT(1);

  Delay_1us(10);

  I2C_SDA_OUT(1);

  Delay_1us(10);

}


回从机ACK,回从机NACK

/**

  * @brief  MCU回复IC ACK信号

  * @param  None

  * @retval None

  */

void I2C_SEND_ACK(void)

{

  I2C_SDA_SET_OUTPUT();

  

  I2C_SDA_OUT(0);

  Delay_1us(10);//

  I2C_SCL_OUT(1);

  Delay_1us(10);

  I2C_SCL_OUT(0);

  Delay_1us(10);

}


/**

  * @brief  MCU回复NACK信号

  * @param  None

  * @retval None

  */

void I2C_SEND_NACK(void)

{

  I2C_SDA_SET_OUTPUT();

  

  I2C_SDA_OUT(1);

//  Delay_1us(10);///

  I2C_SCL_OUT(1);

  Delay_1us(10);

  I2C_SCL_OUT(0);

  Delay_1us(10);

}


从从机读1字节

/**

  * @brief  I2C MCU接收1字节

  * @param  ACK_CHOICE:  数据读取后主机如何回复,I2C_ACK=回复ACK  I2C_NACK=回复NACK  I2C_JUMP_REPLY=跳过回复

  * @retval read_data:   接收的字节

  */

unsigned char I2C_READ_BYTE(unsigned char ACK_CHOICE)

{

  unsigned char read_data=0;

  

  I2C_SDA_SET_INPUT();

  

//  I2C_SCL_OUT(0);//

//  Delay_1us(10);///

  

  for(unsigned char i=0x80; i!=0; i>>=1)

  {

    I2C_SCL_OUT(1);

    Delay_1us(10);

    if(I2C_SDA_IN() == 1)

      read_data |= i;

    I2C_SCL_OUT(0);

    Delay_1us(10);

  }

  I2C_SDA_SET_OUTPUT();

  I2C_SDA_OUT(1);//?????????????????

  

  if(ACK_CHOICE==I2C_ACK)       I2C_SEND_ACK();

  if(ACK_CHOICE==I2C_NACK)      I2C_SEND_NACK();

  

  return read_data;

}


向从机写1字节

/**

  * @brief  I2C MCU发送1字节

  * @param  send_data:  发送的字节

  * @retval ack回复:    I2C_NACK=异常=检测到NACK  I2C_ACK=正常=检测到ACK

  */

unsigned char I2C_SEND_BYTE(unsigned char send_data)

{

  unsigned char ack=I2C_NACK;   //初始值

  unsigned char time_out=200;   //ACK查询次数

  


  I2C_SDA_SET_OUTPUT();

//  I2C_SCL_SET_OUTPUT();

  

//  I2C_SCL_OUT(0);

//  Delay_1us(10);/

  

  for(unsigned char i=0x80; i!=0; i>>=1)

  {

    if(send_data&i)     I2C_SDA_OUT(1);

    else                I2C_SDA_OUT(0);

    I2C_SCL_OUT(1);

    Delay_1us(10);

    I2C_SCL_OUT(0);

    Delay_1us(10);

  }

  

  //开始ACK查询

  I2C_SDA_SET_INPUT();

  I2C_SCL_OUT(1);

  while(time_out--)

  {

    if(I2C_SDA_IN()==1)

      ack=I2C_NACK;

    else

    {

      ack=I2C_ACK;

      break;

    }

    Delay_1us(1);

  }

  

  I2C_SCL_OUT(0);

  

  I2C_SDA_SET_OUTPUT();

  I2C_SDA_OUT(1);//???????????????????

  

  return ack;

}


其他代码

上述全部代码位于i2c.c 源文件中,而下列代码则全部位于i2c.h 头文件。


#ifndef __I2C_H

#define __I2C_H

/* Includes ------------------------------------------------------------------*/

#include "main.h"


/* Private defines -----------------------------------------------------------*/

#define I2C_PORT                GPIOB

#define I2C_SDA_PIN             GPIO_PIN_5

#define I2C_SCL_PIN             GPIO_PIN_4


#define I2C_ACK                 0 //用于接收:SDA=L=从机有回复  用于发送:回复从机ACK

#define I2C_NACK                1 //用于接收:SDA=H=从机未回复  用于发送:回复从机ACK

#define I2C_JUMP_REPLY          2 //调试用

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

void I2C_GPIO_Init(void);

void I2C_SDA_SET_OUTPUT(void);

void I2C_SCL_SET_OUTPUT(void);

void I2C_SDA_SET_INPUT(void);

void I2C_SCL_SET_INPUT(void);


void I2C_SDA_OUT(unsigned char value);

void I2C_SCL_OUT(unsigned char value);

unsigned char I2C_SDA_IN(void);

unsigned char I2C_SCL_IN(void);


void I2C_START(void);

void I2C_STOP(void);


void I2C_SEND_ACK(void);

void I2C_SEND_NACK(void);


unsigned char I2C_READ_BYTE(unsigned char ACK_CHOICE);

unsigned char I2C_SEND_BYTE(unsigned char send_data);


#endif

关键字:STM8S  GPIO  模拟I2C 引用地址:STM8S GPIO模拟I2C的底层代码

上一篇:stm8s103-PWM输出与输入捕获
下一篇:基于IAR开发环境的STM8S模拟IIC代码

推荐阅读最新更新时间:2024-11-17 01:53

使用STM32GPIO端口点亮LED灯(库函数)
1,先定义GPIO端口结构体 GPIO_InitTypeDef LED_GPIOA_InitStruct; 2,使用GPIO端口指定要使用的结构体 LED_GPIOA_InitStruct.GPIO_Pin = GPIO_Pin_2; //指定第2引脚 3,同上设置输出或输入的方式 LED_GPIOA_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出 4,同上设置输出速度 LED_GPIOA_InitStruct.GPI
[单片机]
如何测量MSP430功耗
众所周知,MSP430以其超低功耗而著称。但是很多用户反应,在实际应用中,测量MSP430的功耗时,测量结果和MSP430数据手册相差甚远。其实这里主要涉及到两方面的内容: 1. 如何使用MSP430合理的设计硬件和软件,使整个应用最大限度的达到低功耗? 2. 如何测量MSP430的功耗? 就如何测量MSP430功耗,我来分享一下我个人的经验。 一、未使用的GPIO的处理 为了使MSP430最大限度的达到低功耗,对于MSP430未使用的GPIO而言,应该将其设置为输出;或者是设置为输入,但是将管脚的电平固定,可以通过外部电路将管脚连接至Vcc或者GND,也可使能内部上下拉电阻,将管脚电平固定。 对于MSP4
[单片机]
如何测量MSP430功耗
STM32F103ZET6 —— GPIO
STM32 的 GPIO 可以由软件配置成为几种不同的模式,每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问: A. 芯片侧: 1. 输入: 2. 输出: B. 硬件侧: 对应的单板,有两个GPIO连接到LED上: 使用的是 GPIO 的 Port G 的 Pin13 和 Pin14 脚 C. 代码侧: 配置上述两个 GPIO 工作需要的步骤如下: 1. 使能对应的 GPIO_G 的时钟 2. 配置 GPIO_G13/GPIO_G14 为通用推挽输出,配置口线翻转速度50M 3. 配置完成后,设置端口的输出为1/0即可控制 GPIO 的输出。 1. 时钟设置:
[单片机]
STM32F103ZET6 —— <font color='red'>GPIO</font>
STM8S那些破事
1、中断的使用 EXTI_SetExtIntSensitivity 外部中断控制寄存器 1 (EXTI_CR1) void EXTI_SetExtIntSensitivity(EXTI_Port_TypeDef Port, EXTI_Sensitivity_TypeDef SensitivityValue) { /* Check function parameters */ assert_param(IS_EXTI_PORT_OK(Port)); assert_param(IS_EXTI_SENSITIVITY_OK(SensitivityValue)); /* Set external inte
[单片机]
<font color='red'>STM8S</font>那些破事
GPIO的配置及使用(MC9S08AW60)
基础必备知识 AW60有7个GPIO接口,分别是A、B、C、D、E、F、G。每个接口最多对应8个GPIO引脚,但对每个GPIO接口编程时,寄存器设置都要是8位,只是没有引脚的位无效。用8位二进制数表示寄存器的值,8位二进制数从右向左依次表示为GPIO 0~7个 引脚。以0b开头的数是二进制,0x开头的数是十六进制(0b00001111=0x0f,0b11110000=0xf0,就是把二进制传化为十六进制)。用单片机实现什么功能其实就是对寄存器进行操作。 每个I/O(GPIO)管脚(引脚)的功能受5个寄存器的控制: 一、数据寄存器 (1)命名规则:PT+该端口(接口)的名称+D 如:PTAD、PTBD、PTCD等 (2)设置每个
[单片机]
STM32学习笔记之GPIO的基本使用
楼学习中主要使用的资料有 战舰V3资料盘——教学视频 《STM32F1开发指南-库函数版本_V3.1》 (PDF) 《零死角玩转STM32》 野火出版 使用的学习板为屹讯电子嵌入式平台v2(MCU为 STM32F103RCT6) **某些IO口带有FT标识,代表其最大工作电压达到5V CPU能直接读取外设电平 上拉电阻的作用????????????????? 下拉电阻 CPU能直接读取外部电压变化(模拟量) 0-3.3v 输出控制电路置1,输出由外部电路决定(上拉或下拉) 输出控制电路置0,输出为0 置1置0的写入由CPU执行 输出控制电路的写入由外设模块决定 输出控制电路置1,输出1;置0,输出0。
[单片机]
STM32学习笔记之<font color='red'>GPIO</font>的基本使用
【STM32H7教程】第17章 STM32H7之GPIO的HAL库API
17.1 初学者重要提示 1、 如何阅读HAL库源码的问题 HAL库实现的函数有复杂的,也有简单的,简单的可以直接阅读代码。复杂的代码阅读起来比较耗时间,如果再配合参考手册抠每个寄存器的配置,那就更消耗时间了。所以对于这种函数,用户仅需了解每个部分实行的功能即可,而且HAL库都做了关键注释,以说明这部分实现的功能。所以用户没有必要去抠每个配置是如何实现的,仅需知道实现了什么功能。以后工程项目有需要了解具体配置时,再看即可。 2、 学习本章节前,务必保证已经学习了第15章。 17.2 GPIO涉及到的寄存器 GPIO外设涉及到的寄存器比较少,也容易理解,推荐大家阅读GPIO源码的时候将参考手册中对应的寄存器功能做一个了解
[单片机]
【STM32】GPIO工作原理(八种工作方式分析,附电路图)
STM32F1xx官方资料: 《STM32中文参考手册V10》-第8章通用和复用功能IO(GPIO和AFIO ) 芯片数据手册(datasheet) STM32的GPIO介绍 STM32引脚说明 GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32F103ZET6芯片为144脚芯片,包括7个通用目的的输入/输出口(GPIO)组,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF、GPIOG,同时每组GPIO口组有16个GPIO口。通常简略称为PAx、PBx、PCx、PDx、PEx、
[单片机]
【STM32】<font color='red'>GPIO</font>工作原理(八种工作方式分析,附电路图)
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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