小松的STM32教程(13)—— 驱动外部内存24C02

2023-11-19

预备

学习目标

概述

24cxx.c

#include "24cxx.h" 
#include "delay.h"
#include "delay.h"


void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	//RCC->APB2ENR|=1<<4;//��ʹ������IO PORTCʱ��
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOC, ENABLE );

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //�������
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	IIC_SCL=1;
	IIC_SDA=1;

}
//����IIC��ʼ�ź�
void IIC_Start(void)
{
	SDA_OUT();     //sda�����
	IIC_SDA=1;
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low
	delay_us(4);
	IIC_SCL=0;//ǯסI2C���ߣ�׼�����ͻ��������
}
//����IICֹͣ�ź�
void IIC_Stop(void)
{
	SDA_OUT();//sda�����
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1;
	IIC_SDA=1;//����I2C���߽����ź�
	delay_us(4);
}
//�ȴ�Ӧ���źŵ���
//����ֵ��1������Ӧ��ʧ��
//        0������Ӧ��ɹ�
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA��������
	IIC_SDA=1;delay_us(1);
	IIC_SCL=1;delay_us(1);
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//ʱ�����0
	return 0;
}
//����ACKӦ��
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//������ACKӦ��
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//IIC����һ���ֽ�
//���شӻ�����Ӧ��
//1����Ӧ��
//0����Ӧ��
void IIC_Send_Byte(u8 txd)
{
    u8 t;
	SDA_OUT();
    IIC_SCL=0;//����ʱ�ӿ�ʼ���ݴ���
    for(t=0;t<8;t++)
    {
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;
		delay_us(2);   //��TEA5767��������ʱ���DZ����
		IIC_SCL=1;
		delay_us(2);
		IIC_SCL=0;
		delay_us(2);
    }
}
//��1���ֽڣ�ack=1ʱ������ACK��ack=0������nACK
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA��������
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0;
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;
		delay_us(1);
    }
    if (!ack)
        IIC_NAck();//����nACK
    else
        IIC_Ack(); //����ACK
    return receive;
}

void AT24CXX_Init(void)
{
	IIC_Init();
}

u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{				  
	u8 temp=0;		  	    																 
    IIC_Start();  
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	   //�������
		IIC_Wait_Ack();
		IIC_Send_Byte(ReadAddr>>8);//���͸ߵ�ַ
		IIC_Wait_Ack();		 
	}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //����������ַ0XA0,д���� 	 

	IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr%256);   //���͵͵�ַ
	IIC_Wait_Ack();	    
	IIC_Start();  	 	   
	IIC_Send_Byte(0XA1);           //�������ģʽ			   
	IIC_Wait_Ack();	 
    temp=IIC_Read_Byte(0);		   
    IIC_Stop();//����һ��ֹͣ����	    
	return temp;
}

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{				   	  	    																 
    IIC_Start();  
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	    //�������
		IIC_Wait_Ack();
		IIC_Send_Byte(WriteAddr>>8);//���͸ߵ�ַ
 	}else
	{
		IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //����������ַ0XA0,д���� 
	}	 
	IIC_Wait_Ack();	   
    IIC_Send_Byte(WriteAddr%256);   //���͵͵�ַ
	IIC_Wait_Ack(); 	 										  		   
	IIC_Send_Byte(DataToWrite);     //�����ֽ�							   
	IIC_Wait_Ack();  		    	   
    IIC_Stop();//����һ��ֹͣ���� 
	delay_ms(10);	 
}

void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{  	
	u8 t;
	for(t=0;t<Len;t++)
	{
		AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
	}												    
}


u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{  	
	u8 t;
	u32 temp=0;
	for(t=0;t<Len;t++)
	{
		temp<<=8;
		temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1); 	 				   
	}
	return temp;												    
}

u8 AT24CXX_Check(void)
{
	u8 temp;
	temp=AT24CXX_ReadOneByte(255);//����ÿ�ο�����дAT24CXX			   
	if(temp==0X55)return 0;		   
	else//�ų���һ�γ�ʼ�������
	{
		AT24CXX_WriteOneByte(255,0X55);
	    temp=AT24CXX_ReadOneByte(255);	  
		if(temp==0X55)return 0;
	}
	return 1;											  
}


void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
	while(NumToRead)
	{
		*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);	
		NumToRead--;
	}
}  

void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
	while(NumToWrite--)
	{
		AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
		WriteAddr++;
		pBuffer++;
	}
}

24cxx.h

#ifndef __24CXX_H
#define __24CXX_H
#include "myiic.h"   
#include "sys.h"

#define AT24C01		127
#define AT24C02		255
#define AT24C04		511
#define AT24C08		1023
#define AT24C16		2047
#define AT24C32		4095
#define AT24C64	    8191
#define AT24C128	16383
#define AT24C256	32767

#define SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

#define IIC_SCL    PCout(12) //SCL
#define IIC_SDA    PCout(11) //SDA
#define READ_SDA   PCin(11)  //����SDA
#define EE_TYPE AT24C02

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);

u8 AT24CXX_ReadOneByte(u16 ReadAddr);							//ָ����ַ��ȡһ���ֽ�
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);		//ָ����ַд��һ���ֽ�
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);//ָ����ַ��ʼд��ָ�����ȵ�����
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len);					//ָ����ַ��ʼ��ȡָ����������
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);	//��ָ����ַ��ʼд��ָ�����ȵ�����
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);   	//��ָ����ַ��ʼ����ָ�����ȵ�����
u8 AT24CXX_Check(void);  //�������
void AT24CXX_Init(void); //��ʼ��IIC

#endif

主函数调用

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "key.h"
#include "24cxx.h"

const u8 TEXT_Buffer[]="Kafen Wong EDIL";
#define SIZE sizeof(TEXT_Buffer)

 int main(void)
 {
	delay_init();
	OLED_Init();//显示屏初始化
	u8 datatemp[SIZE];
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	KEY_Init();				//按键初始化
	AT24CXX_Init();			//芯片初始化

 	while(AT24CXX_Check())//检测不到24c02
	{
 		OLED_Refresh();
		OLED_ShowString(0,0,"CANT OPEN",16,1);
	}

 	OLED_ShowString(0,0,"OK!",16,1);
 	static int ii=0;

	while(1)
	{
		OLED_Refresh();
		if(KEY_Scan())//WK_UP 按下,写入24C02
		{
			ii++;
			if(ii%2){
				OLED_Clear();
				OLED_Refresh();
				OLED_ShowString(0,0,"Start Write",16,1);
				AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
				OLED_ShowString(0,16,"Finished",16,1);
			}
			else{
				OLED_Clear();
				OLED_Refresh();
				OLED_ShowString(0,0,"Start Read",16,1);
				AT24CXX_Read(0,datatemp,SIZE);
				OLED_ShowString(0,16,"Data is",16,1);
				OLED_ShowString(0,32,datatemp,16,1);
			}
		}
	}
}

作业

  1. 尝试把库中IIC的部分独立出来,并且将OLED库的IIC函数删去,使用独立出来的IIC库
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小松的STM32教程(13)—— 驱动外部内存24C02 的相关文章

  • 51单片机 数码管中断操作

    实践目的 1 掌握中断的概念和思想 2 掌握51单片机中断系统和相关软硬件设计 实践内容 1 利用单片机的P0口接数码管的字段脚 P1 0脚接共阴极 P3 2 P3 3引脚接独立按键产生外部中断信号 编写程序 当程序正常运行时数码管显示H字
  • 以字符串形式接收数字(uart)

    我正在尝试通过 uart 接收一个包装为字符串的数字 我发送数字 1000 所以我得到 4 个字节 空字符 但是 当我使用 atoi 将数组转换为数字并将整数与 1000 进行比较时 我并不总是得到正确的数字 这是我用于接收号码的中断处理函
  • 在 MCU 内部 FLASH 中从一个固件跳转到另一个固件

    我目前正在开发针对 STM32F030C8 的引导加载程序固件应用程序 我在分散文件中指定引导加载程序应用程序将占用主内存位置 0x08000000 到 0x08002FFF 扇区 0 到扇区 2 我还编写了一个主固件应用程序 存储在0x0
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • HAL库学习

    CMSIS简介 CMSIS Cortex Microcontroller Software Interface Standard 微控制器软件接口标准 由ARM和其合作的芯片厂商 ST NXP 软件工具厂商 KEIL IAR 共同制定的标准
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • STM32H5 Nucleo-144 board开箱

    文章目录 开发板资料下载 目标 点亮LD1 绿 LD2 黄 和LD3 红 三个LED灯 开箱过程 博主使用的是STM32CubeMX配置生成代码 具体操作如下 打开STM32CubeMX File gt New project 选择开发板型
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板

随机推荐

  • WIN10 修改用户下文件夹的名称

    转载note 我是为了解决正当防卫3不能存档 我的用户名当初设置的数字 转载的原因是 走了很多百度知道和经验的弯路 如果有人看到就别走了 我因为走了弯路前弄后弄导致原先的个人数据文件还丢失 只得跳出步骤新建用户 在PE下复制还有的数据 所以
  • 在windows系统安装linux

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 说明 二 步骤 1 利用WindowsADK安装windows 1 Windows 评估和部署工具包 ADK 包括 CopyPE 和 MakeWinPEM
  • no matching host key type found. Their offer: ssh-rsa 问题解决

    最近升级了Mac OS Ventura 13 0 1后发现ssh指定密钥登录服务器失败 no matching host key type found Their offer ssh rsa 进入当前用户的 ssh目录发现比之前系统多了一个
  • Ubuntu20.04安装qemu错误解决方法

    1 如果运行 configure显示没有找到pip sudo apt get install phthon3 pip 2 如果运行 configure显示 ninja error opening build log Permission d
  • com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区别

    com mysql jdbc Driver 是 mysql connector java 5中的 com mysql cj jdbc Driver 是 mysql connector java 6中的 1 JDBC连接Mysql5 com
  • [共同学习] 平衡二叉树浅见

    平衡二叉树 平衡二叉树的概念 AVL树结点的定义 AVL树的插入 左左 右单旋 右右 左单旋 左右 先左旋 再右旋 右左 先右旋 再左旋 AVL树的验证 验证其为二叉搜索树 验证其为平衡树 AVL树的性能 AVL树的实现 感悟 以上 二叉搜
  • 三分钟实现一个react-router-dom5.0的路由拦截(导航守卫)

    不同于vue 通过在路由里设置meta元字符实现路由拦截 在使用 Vue 框架提供了路由守卫功能 用来在进入某个路有前进行一些校验工作 如果校验失败 就跳转到 404 或者登陆页面 比如 Vue 中的 beforeEnter 函数 rout
  • element upload上传视频,获取本地url地址和时长

    获取视频的时长参考了文章 https www cnblogs com 65Seeker p 11466824 html 1 URL createObjectURL 静态方法会创建一个 DOMString 其中包含一个表示参数中给出的对象的U
  • SpringBoot项目中ModelMapper配置以及使用

    项目中对象与对象赋值转换使用的频率非常的高 比如数据库表实体对象 Entity 与业务类对象 Model 之间的赋值传递 或者模型对象 Model 与视图对象 ViewModel 之间的赋值传递 如果我们一个一个字段的赋值 将是非常繁琐并且
  • vue+element -UI前端Excel 文件导入数据

    完成的效果图如下 会进行数据筛选 根据你上传的物业名称跟数据库的名称对应 在这里我用到了一个插件 需要在在main js中全局引入 import export excel to json export json to excel from
  • linux之命名空间

    1 什么是命名空间 Linux中的命名空间 namespaces 是一种轻量级的虚拟化技术 ps docker就是依赖这个原理实现的 让进程看起来像是在自己的独立系统中运行 也就是说进程只能看到相同命名空间内的进程和资源 而看不到其他命名空
  • PG向表中添加新列时判断存在性

    以下是可以在命令行中执行的 SQL 语句 用于向表中添加新列并判断存在性 DO BEGIN BEGIN ALTER TABLE your table name ADD COLUMN IF NOT EXISTS your column nam
  • 服务器torchserver部署全流程踩坑记录

    服务器torchserver部署全流程踩坑记录 部署结果展示 一 Python环境 一 创建虚拟环境 二 安装torch cuda等 三 Python环境移植 二 java jdk环境 一 java jdk安装 1 sudo安装 需要sud
  • 使用selenium爬取唯品会

    使用selenium爬取唯品会 1 基本步骤 2 通过程序控制浏览器下拉滚动条获取加载信息 3 完成这个爬虫程序 使用selenium爬取动态加载的网页 爬取唯品会的商品 1 基本步骤 首先 创建一个浏览器驱动driver 查看唯品会页面u
  • 我的世界服务器聊天显示坐标,我的世界端游怎么显示坐标

    手机游戏cf的VIP等级会显示在最终游戏CF上吗 H 是的 无需感谢 我的世界如何环绕 单击显示不坐吗 前提是必须有一个区域插件 用木斧对角指向两个点 住所 牛仔竞技插件 您只能绘制自己的区域 其他 无法破坏或改变您的领土 每个玩家可以拥有
  • OpenCV机器视觉-识别红绿颜色

    识别红绿颜色 识别车道线 车道线检测 使用opencv来完成一个车道线检测的案例 完成这样的案例我们需要经历哪些步骤呢 我们先来思考一下解决问题的思路 当前情况下 摄像头拍出了很多的东西 例如路边的杂草远方的山 但是在我们自动驾驶的过程中
  • 【华为OD机试真题】补种未成活胡杨(C&C++&java&python&JavaScript&go)100%通过率【2023(B卷)100分】

    补种未成活胡杨 题目描述 近些年来 我国防沙治沙取得显著成果 某沙漠新种植 N 棵胡杨 编号 1 N 排成一排 一个月后 有 M 棵胡杨未能成活 现可补种胡杨 K 棵 请问如何补种 只能补种 不能新种 可以得到最多的连续胡杨树 输入描述 N
  • 【Android】Android ANR产生过程与分析方法

    前言 Android ANR问题一直是比较难解决的问题 一来它比较难以复现 二来复现后也不太好分析 这篇文章梳理一下ANR产生的过程以及出现ANR拿到日志文件如何定位原因 其实关于ANR线上监控也是比较棘手的 看了这篇文章我们再去看一些AN
  • linux内存调节之CMA

    本文贴代码过头了 以后想起来再优化一下吧 目录 概述 数据结构 构建初始化 DTS CONFIG DMA CMA 页表与物理页初始化 分配器激活 分配器使用 CMA部署 实战 概述 CMA Contiguous Memory Allocat
  • 小松的STM32教程(13)—— 驱动外部内存24C02

    预备 学习目标 概述 24cxx c include 24cxx h include delay h include delay h void IIC Init void GPIO InitTypeDef GPIO InitStructur