GPIO模拟IIC通信测量环境光

目录

iic.h

iic.c

ap3216c.h

ap3216.c

main.c

实验效果


iic.h

#ifndef __IIC_H__
#define __IIC_H__

#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
//SDA 数据线为PF15
//SCL 时钟线为PF14

//配置PF15为输出模式
#define SET_SDA_OUT do{GPIOF->MODER &=(~(0x3<<30));\
                       GPIOF->MODER |=(0x1<<30);}while(0)

//配置PF15为输入模式
#define SET_SDA_IN  do{GPIOF->MODER &=(~(0x3<<30));}while(0)

//读取PF15输入寄存器的值
#define I2C_SDA_READ GPIOF->IDR & (0x1<<15)

//PF14输出高电平、低电平
#define I2C_SCL_H  do{GPIOF->BSRR |= (0x1<<14);}while(0)
#define I2C_SCL_L  do{GPIOF->BRR |= (0x1<<14);}while(0)

//PF15输入高电平、低电平
#define I2C_SDA_H do{GPIOF->BSRR |= (0x1<<15);}while(0)
#define I2C_SDA_L do{GPIOF->BRR |= (0x1<<15);}while(0)


void delay_us(void);
//模拟I2C
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write_byte(unsigned char  dat);
unsigned char i2c_read_byte(unsigned char ack);
unsigned char i2c_wait_ack(void);       
void i2c_ack(void);
void i2c_nack(void);

#endif

iic.c

#include "iic.h"

//微妙级的延时
void delay_us(void){
    unsigned int i=2000;
    while(i--);
}
//模拟I2C

//I2C初始化
void i2c_init(void){
    //GPIOF时钟使能
    RCC->MP_AHB4ENSETR |= (0x1<<5);

    //配置PF14、PF15为输出模式
    GPIOF->MODER &= (~(0xF<<28));
    GPIOF->MODER |= (0x5<<28);

    //配置PF14、PF15为推挽输出
    GPIOF->OTYPER &= (~(0x3<<14));

    //配置PF14、PF15输出速度为超高速
    GPIOF->OSPEEDR |= (0xF<<28);

    //配置PF14、PF15无上拉下拉
    GPIOF->PUPDR &= (~(0xF<<28));

    //将SCL和SDA输出高电平
    I2C_SCL_H;
    I2C_SDA_H;

}

//发送起始信号
void i2c_start(void){

    //设置SDA为输出模式
    SET_SDA_OUT;
    //拉高数据线和时钟线
    I2C_SCL_H;
    I2C_SDA_H;
    delay_us();  //延时
    //拉低数据线
    I2C_SDA_L;
    delay_us();  //延时

    //拉低时钟线
    I2C_SCL_L;

}

//发送停止信号
void i2c_stop(void){
    //设置SDA为输出模式
    SET_SDA_OUT;

    //拉低时钟线
    I2C_SCL_L;
    delay_us();
    delay_us();
    //修改数据线为低电平
    I2C_SDA_L;
    delay_us();
    //拉高时钟线
    I2C_SCL_H;
    delay_us();
    //拉高数据线
    I2C_SDA_H;

}

//发送数据
void i2c_write_byte(unsigned char  dat){
    unsigned int i;
    //PF14配置为输出模式
    SET_SDA_OUT;
    for(i=0;i<8;i++){
        //拉低时钟线
        I2C_SCL_L;
        delay_us();
        //修改数据线的值
        if(dat&(0x1<<7)){
            I2C_SDA_H;
        }
        else{
            I2C_SDA_L;
        }
        delay_us();
        //拉高时钟线
        I2C_SCL_H;
        delay_us();   //拉高是时钟线后延时 
        delay_us();   //延时等待从机读取
        dat<<=1;
    }
}

//读取数据
unsigned char i2c_read_byte(unsigned char ack){
    //配置为输入模式
    SET_SDA_IN;
    unsigned char data;
    for(unsigned int i=0;i<8;i++){
        //从机需要向寄存器写入数据
        //所有需要拉低时钟线
        I2C_SCL_L;
        delay_us();   //延时
        delay_us();   //等待从机写入数据
        //拉高时钟线读取数据
        I2C_SCL_H;
        delay_us();    //延时
        data<<=1;
        if(I2C_SDA_READ){
           data|=0x1; 
        }
        else data|=0x0;
    }
    if(!ack){
        i2c_nack();
    }
    else{
        i2c_ack();
    }
    //返回读取的数值
    return data;
}

//等带从机ack
unsigned char i2c_wait_ack(void){

    //拉低时钟线,修改SDA电平
    I2C_SCL_L;
    delay_us();
    I2C_SDA_H; //释放给从机
    delay_us();
    //SDA配置为输入模式
    SET_SDA_IN;
    delay_us();
    delay_us();
    //拉高时钟线读取从机ack
    I2C_SCL_H;
    delay_us();
    if(I2C_SDA_READ){
        return 1;
    }
    I2C_SCL_L;
    return 0;
}    

//ack应答
void i2c_ack(void){
    //配置为输出模式
    SET_SDA_OUT;

    //拉低时钟线
    I2C_SCL_L;
    delay_us();

    //拉低数据线
    I2C_SDA_L;
    delay_us();
    //拉高时钟线
    I2C_SCL_H;
    delay_us();
    delay_us();
      //拉低时钟线?
    I2C_SCL_L;
}

//非ack应答
void i2c_nack(void){
 //配置为输出模式
    SET_SDA_OUT;

    //拉低时钟线
    I2C_SCL_L;
    delay_us();

    //拉高数据线
    I2C_SDA_H;
    delay_us();
    //拉高时钟线
    I2C_SCL_H;
    delay_us();
    delay_us();

    //拉低时钟线?
    I2C_SCL_L;
    
}

ap3216c.h

#ifndef __AP3216C_H__
#define __AP3216C_H__

//ap3216c初始化
void ap3216c_init();
void ap3216c_init1();
//读取ap3216c环境光
unsigned char ap3216c_read_alsl();
unsigned char ap3216c_read_alsh();

#endif

ap3216.c

#include "ap3216c.h"
#include "iic.h"
//ap3216c初始化
void ap3216c_init(){
    //发送起始信号
    i2c_start();
    //发送七位从机地址+1位写标志  0x1E | 0x0 = 0x3c
    i2c_write_byte(0x3c);
    //等待从机应答
    i2c_wait_ack();
    //发送8位寄存器地址0x00
    i2c_write_byte(0x00);
    //等待从机应答
    i2c_wait_ack();
    //写入数据0x3A,si7006初始值
    i2c_write_byte(0x1);
    //等待应答
    i2c_wait_ack();
    //发送停止信号 
    i2c_stop();
}


//读取ap3216c环境光
unsigned char ap3216c_read_alsl(){
    //发送起始信号
    i2c_start();
    //发送七位从机地址+1位写标志  0x1E | 0x0 = 0x3C
    i2c_write_byte(0x3C);
    //等待从机应答
    i2c_wait_ack();
    //发送8位寄存器地址0xE3
    i2c_write_byte(0x0C);
    //等待从机应答
    i2c_wait_ack();
    //发送重复开始信号
    i2c_start();
    //发送从机地址和读写标志  0x40 | 0x1 = 0x81
    i2c_write_byte(0x3D);
    //等待从机应答
    i2c_wait_ack();
    //读取环境光
    char als_l;
    als_l=i2c_read_byte(1);
    //发送应答

    //发送停止信号
    i2c_stop();
    return als_l;

}
//读取ap3216c环境光
unsigned char ap3216c_read_alsh(){
    //发送起始信号
    i2c_start();
    //发送七位从机地址+1位写标志  0x1E | 0x0 = 0x3C
    i2c_write_byte(0x3C);
    //等待从机应答
    i2c_wait_ack();
    //发送8位寄存器地址0xE3
    i2c_write_byte(0x0D);
    //等待从机应答
    i2c_wait_ack();
    //发送重复开始信号
    i2c_start();
    //发送从机地址和读写标志  0x40 | 0x1 = 0x81
    i2c_write_byte(0x3D);
    //等待从机应答
    i2c_wait_ack();
    //读取环境光
    char als_h;
    als_h=i2c_read_byte(1);
    //发送应答

    //发送停止信号
    i2c_stop();
    return als_h;

}

main.c

#include "gpio.h"
#include "led.h"
#include "uart4.h"
#include "keyip.h"
#include "iic.h"
#include "si7006.h"
#include "ap3216c.h"
extern void printf(const char *fmt, ...);
int main()
{
	led1_init();
	i2c_init();
	ap3216c_init();
	unsigned short als;
	unsigned char als_l;
	unsigned char als_h;
	while (1)
	{
		als_l=ap3216c_read_alsl(1);
		als_h=ap3216c_read_alsh(1);
		als=((unsigned short)als_h<<8) | als_l;
		printf("als=%d\n",als);
		if(als<100){
			led1_ctl(1);
		}
		else{
			led1_ctl(0);
		}
		delay(1000);
	
	}
	return 0;
}

实验效果

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

医药进出口交易|基于SSM+vue的医药进出口交易系统的设计与实现(源码+数据库+文档)

医药进出口交易系统 目录 基于SSM&#xff0b;vue的医药进出口交易系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 5.1系统登录 5.2管理员功能模块 5.3仓储部门功能模块 5.4业务部门功能模块 5.5供应部门功能模块 5.6财务部功能模块 5.7客户功能模块 …

【BUG】流式响应requests得到: ping - 和时间戳

前情提要 运行Langchain-Chatchat项目&#xff0c;使用自定义请求访问API Server流式输出 报错展示 b: ping - 2024-05-22 00:46:04.83252000:00\r\n\r\n报错原因 这通常是由于 Server-Sent Events (SSE) 实现中使用的“心跳”机制&#xff0c;以确保连接保持活跃。一些 SSE…

反序列化漏洞(JBoss、apache log4、apache Shiro、JWT)Weblogic未授权访问、代码执行、任意上传

1.1什么是反序列化 就是把一个对象变成可以传输的字符串&#xff0c;目的就是为了方便传输。假设&#xff0c;我们写了一个class&#xff0c;这个class里面存有一些变量。当这个class被实例化了之后&#xff0c;在使用过程中里面的一些变量值发生了改变。以后在某些时候还会用到…

附代码:策略常用-正余弦优化算法

正余弦优化算法作为群智能优化算法的一种, 正弦余弦算法 (sine cosine algorithm, SCA) 是 2016 年由 Mirjalili 提出的一种新型仿自然优化算法, 通过创建多个随机候选解, 利用正余弦函数的数学性质来平衡算法在搜系过程中的全局探索和局部开发能力。该算法具有结构简单、参数少…

鸿蒙开发接口应用程序包管理:【ApplicationInfo】

ApplicationInfo 说明&#xff1a; 本模块首批接口从API version 7 开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。…

ARTS Week 29

Algorithm 本周的算法题为 2413. 最小偶倍数 给你一个正整数 n &#xff0c;返回 2 和 n 的最小公倍数&#xff08;正整数&#xff09;。 示例 1&#xff1a;输入&#xff1a;n 5输出&#xff1a;10解释&#xff1a;5 和 2 的最小公倍数是 10 。 实现代码如下&#xff1a; con…

P6【力扣144,94,145】【数据结构】【二叉树遍历】C++版

【144】二叉树的前序遍历 1、递归法&#xff1a; class Solution { public:void preorder(TreeNode* root, vector<int> &res){if(root nullptr){return;}res.push_back(root->val);preorder(root->left, res);preorder(root->right, res);}vector<in…

AI--构建检索增强生成 (RAG) 应用程序

LLM 所实现的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 (RAG) 的技术。 典型的 RAG 应用程序有两个主要组件 索引&#xff1a;从源中提取数据并对其进行索引的管道。这通常在线下…

递增链表去重

题目描述&#xff1a; 题目思路&#xff1a; 1.链表内的val是递增的&#xff0c;所以相同的值只会连续重复地出现。 2.设置三个指针&#xff1a; ①指向头结点指针&#xff0c;用于返回链表 ②指向返回链表链尾的指针&#xff0c;用于在新链表添加结点 ③遍历旧链表结点的…

基于地理坐标的高阶几何编辑工具算法(5)——合并相交面

文章目录 工具步骤应用场景算法输入算法输出算法示意图算法原理 工具步骤 选中一个面&#xff0c;点击“合并相交面”工具&#xff0c;选择其他相邻面&#xff0c;空格执行合并。 应用场景 用于将相邻或相交的同类型几何面进行合并&#xff0c;达到综合效果。 算法输入 待…

单元测试—BMI脚本设计

BMI例题如下&#xff1a; BMI中国计算标准&#xff1a;体质指数&#xff08;BMI&#xff09;体重&#xff08;kg&#xff09;身高^2&#xff08;m&#xff09; 例如&#xff1a;一个人的身高为1.75米,体重为68千克&#xff0c;他的BMI68/(1.75^2)22.2&#xff08;千克/米^2&a…

【堡垒机小知识】堡垒机和接口机的重要区别分析

在企业IT架构管理中&#xff0c;接口机和堡垒机各自扮演着不可或缺的角色。但不少IT小伙伴对于两者不是很了解&#xff0c;不知道两者之间有什么区别&#xff0c;今天我们就来一起分析一下。 堡垒机和接口机的重要区别分析 1、功能区别 接口机主要用于数据库层面的数据交换和…

构建进攻性的网络安全防护策略

进攻性安全&#xff08;Offensive security&#xff09;是指一系列主动安全策略&#xff0c;这些策略与恶意行为者在现实世界的攻击中使用的策略相同&#xff0c;区别在于其目的是加强而非损害网络安全。常见的进攻性安全方法包括红队、渗透测试和漏洞评估。 进攻性安全行动通…

【漏洞复现】用友U8 CRM uploadfile 文件上传致RCE漏洞

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP&#xff0c;主要聚焦成长型、创新型企业&#xff0c;提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友 U8 CRM客户关系管理系统 uploadfle.php 文件存在任意文件上传漏洞&#xff0c;未经身份验证的攻击者通过漏洞上传…

Go 切片常用操作与使用技巧

1.什么是切片 在 Go 语言中的切片&#xff08;slice&#xff09;是一种灵活的动态数组&#xff0c;它可以自动扩展和收缩&#xff0c;是 Go 语言中非常重要的数据结构之一。切片是基于数组实现的&#xff0c;它的底层是数组&#xff0c;可以理解为对底层数组的抽象。它会生成一…

二十五篇:嵌入式系统揭秘:基础理论与实践探索

嵌入式系统揭秘&#xff1a;基础理论与实践探索 1. 嵌入式系统的定义与特性 1.1 详细解释 嵌入式系统&#xff0c;作为一种特殊的计算机系统&#xff0c;其设计目的是为了执行一个或多个特定的功能。与通用计算机相比&#xff0c;嵌入式系统通常被集成到更大的设备中&#xf…

基于地理坐标的高阶几何编辑工具算法(8)——整形面

文章目录 工具步骤应用场景算法输入算法输出算法示意图算法原理工具步骤 选中面,点击“整形面”工具,绘制一条和面至少两个交点的线,双击结束。 应用场景 快速修改一个几何面的局部形状。 算法输入 一个待修改的面p,和一条绘制的线l 算法输出 修改后的面 算法示意图…

(Qt) 默认QtWidget应用包含什么?

文章目录 ⭐前言⭐创建&#x1f6e0;️选择一个模板&#x1f6e0;️Location&#x1f6e0;️构建系统&#x1f6e0;️Details&#x1f6e0;️Translation&#x1f6e0;️构建套件(Kit)&#x1f6e0;️汇总 ⭐项目⚒️概要⚒️构建步骤⚒️清除步骤 ⭐Code&#x1f526;untitled…

Java——抽象类与接口的区别

定义区分&#xff1a; 抽象类&#xff1a;抽象类是用来捕捉子类的通用特性的 。它不能被实例化&#xff0c;只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板 接口&#xff1a;接口是抽象方法的集合。如果一个类实现了某个接口&#xff0c;那么它就继承了这个接…

第二证券今日投资参考:5月国产游戏版号发放 猪价加速上涨

昨日&#xff0c;两市股指盘中震荡上扬&#xff0c;沪指盘中续创年内新高&#xff0c;创业板指一度涨超1%。到收盘&#xff0c;沪指涨0.54%报3171.15点&#xff0c;深证成指涨0.43%报9750.82点&#xff0c;创业板指涨0.59%报1875.93点&#xff0c;上证50指数涨0.34%&#xff1b…