GD32E230C8T6《调试篇》之 (软件) IIC通信(主机接收从机) + GN1650驱动芯片 + 按键 + 4位8段数码管显示 (成功)

GD32E230C8T6《调试篇》之 (软件) IIC通信 + GN1650驱动芯片 + 4位8段数码管显示(成功)

  • IIC是什么
  • IIC简介
    • 1)IIC总线物理连接
    • 2)IIC时序协议
  • 按键扫描
  • 代码
    • 1)DIG2短按只++一次,长按超过1s 一直 ++;DIG3短按只 - - 一次,长按超过1s 一直 - -

IIC是什么

IIC也称I2C,是一个多主从的串行总线,由飞利浦公司发明的通讯总线,属于半双工同步传输类总线,仅由两条线就能完成多机通讯,一条SCL时钟线,另外一条双向数据线SDA,IIC总线要求每个设备SCL/SDA线都是漏极开路模式,因此必须带上拉电阻才能正常工作。I2C协议占用引脚少,硬件实现简单,可扩展性强,I2C数据传输速率有标准模式(100kbps)、快速模式(400kbps)和高速模式(3.4Mbps)。

IIC简介

IIC总线的SDA和SCL两根总线需要上拉,使总线处于空闲状态。IIC总线一共有两种状态、四种信号。除此之外还需要了解IIC总线的数据有效性。

1)IIC总线物理连接

SDA 和SCL 都是双向线路,都通过一个电流源或上拉电阻连接到正的电源电压。当总线空闲时,这两条线路都是高电平。连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与的功能。
总线器件数目:由于每一个IIC器件在IIC总线上都有一个确切的7位地址码,这也意味着一条IIC总线上最多可链接127(0X00位地址不使用)个地址互不相同的IIC器件。但在单条IIC总线上链接不多与127个器件的同时,必须要满足总线电容不能超过400pF(协议规定),总线之所以规定电容大小是因为,IIC的OD要求外部有电阻上拉,电阻和总线电容产生了一个RC延时效应,电容越大信号的边沿就越缓,有可能带来信号质量风险。传输速度越快,信号的窗口就越小,上升沿下降沿时间要求更短更陡峭,所以RC乘积必须更小。实际设计中经验值大概是8个器件左右。
在这里插入图片描述

2)IIC时序协议

时序图:
在这里插入图片描述
IIC总线进行数据传送时,在SCL的每个时钟脉冲期间传输一个数据位,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有在时钟线SCL上的信号为低电平期间,数据线SDA上的高电平或低电平状态才允许变化,因为当SCL是高电平时,数据线SDA的变化被规定为控制命令(START或STOP,也就是起始信号和停止信号)。
在这里插入图片描述
IDLE表示总线空闲状态。此状态下时钟信号SCL和数据信号SDL均为高电 平,此时无I2C设备工作。时钟线(SCL)和数据线(SDA)接上拉电阻,默认高电平,就是为了表示总线是空闲状态。
在这里插入图片描述

表示起始状态。在空闲状态下,时钟信号SCL继续保持高电平,数据信号SDL出现由高电平转换为低电平的下降沿,此时产生一个起始信号,与总线相连的I2C设备检测到起始信号之后,进入起始状态等待控制字节的输入。

在这里插入图片描述

I2C通信的停止信号由主设备发出,SCL保持高电平,SDA由低电平跳变到高电平。

在这里插入图片描述

应答信号接收端收到有效数据后需要向对方响应的信号,发送端每发送一个字节(8位)数据,在第9个时钟周期释放数据线去接收对方的应答。
在第9个时钟周期:
当SDA是低电平为有效应答(ACK),表示对方接收成功;
当SDA是高电平为无效应答(NACK),表示对方没有接收成功。
注意:数据发射端需要在第9个时钟周期等待接收端的应答信号

IIC协议的读写操作都是一字节大小,从高到低收发数据

在这里插入图片描述

在这里插入图片描述
————————————————
版权声明:本文为CSDN博主「烟雨江南、」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guyuani/article/details/127709375

以上内容为转载!!! 下面是自己写的

按键扫描

GN1650 芯片有按键消抖,所以不需要软件消抖;

代码

1)DIG2短按只++一次,长按超过1s 一直 ++;DIG3短按只 - - 一次,长按超过1s 一直 - -


const uint8_t LEDENCODE[] = {0x03F,0x006,0x05B,0x04F,0x066,0x06D,0x07D,0x007,0x07F,0x06F};
//const LEDNUM[][3] = {{0x38,0x3F,0x3E,0x79},{},{}};


#define READ_SDA gpio_input_bit_get(GPIOB,GPIO_PIN_7)
#define LEDDOT 0x80
#define MAXNUM  10

#define TIMEPRESS  350 //key press times
#define DIG1 17
#define DIG2 25
#define DIG3 21
#define DIG4 29
#define ADDRMAX 512

uint8_t i;

uint16_t value=0;

void myGPIO_init(void)
{
	 /* enable GPIOB clock */
	 rcu_periph_clock_enable(RCU_GPIOA);	
		
	 gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_0);//PB6_42  I2C0_SCL GPIO_OTYPE_PP推挽输出
	 gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0);	
}

/****** 按键处理函数
*一定不能有do while , delay 等阻塞语句,要快进快出,main函数有更重要的事情要做
******/
void keycheck(void)
{
	uint16_t KeyNum;
	uint16_t LastKeyNum = 0;
	static uint8_t Keyleased=1,fastCnt=0;
	static uint16_t keydowntime = 0;
	//uint8_t lontimeflag = 1;
	
	KeyNum = GetKey();
	switch(KeyNum)
	{
		case DIG2:
			
			if(keydowntime++ >= TIMEPRESS )//long press ++
			{
				keydowntime=TIMEPRESS;
				if(++fastCnt>=10)//add press times 分频
				{
					fastCnt=0;
					value++;
					if(value > ADDRMAX) value = 1;  //512 to 1
				}
			}
			else if(Keyleased && keydowntime < TIMEPRESS )//short press ++
			{
				value++;	
				Keyleased = 0;//keydown locked  加锁
				if(value > ADDRMAX) value = 1;    //512 to 1
			}
			break;	
		
		case DIG3:	
			
			if( keydowntime++ >= TIMEPRESS)//long press --
			{	
				keydowntime=TIMEPRESS;
				if(++fastCnt>=10)//add press times 分频
				{
					fastCnt=0;
					value--;
					if(value == 0) value = ADDRMAX;   //0 to 512
				}
			}
			else if(Keyleased  && keydowntime++ < TIMEPRESS )//short press --
			{
				value--;
				Keyleased=0; //keydown locked	加锁
				if(value == 0) value = ADDRMAX;   //0 to 512
			}
			break;
			
		default:
			
			Keyleased=1;//keydown loosed
		
			fastCnt=0;

			keydowntime = 0;

			break;
	}
}

//主函数处理
int main(void)
{
	uint8_t flag = 0;
	
	systick_config();
		
	myGPIO_init();
	
	delay_ms(10);
 	
	i2c_init();

    while(1)
	{
		flag =!flag;
		gpio_bit_write(GPIOA,GPIO_PIN_0,flag);
		delay_ms(1);
		
		keycheck();
		GN1650_display();
				
		//do work1		
		//do work2				
	} 
}

/********** 数码管显示 **********/
void  GN1650_display(void)	
{		
	GN1650_Wrt_RAM(0x68,LEDENCODE[value/1000%10]);//high //0x48 系统指令  0x41//4级亮度 8段显示 显示开
	GN1650_Wrt_RAM(0x6A,LEDENCODE[value/100%10] );//   | LEDDOT);
	GN1650_Wrt_RAM(0x6C,LEDENCODE[value/10%10]);
	GN1650_Wrt_RAM(0x6E,LEDENCODE[value%10]); //low
	
	GN1650_Wrt_RAM(0x48,0x01);
	
//	GN1650_Wrt_RAM(0x68,LEDENCODE[value/1000%10]);//high //0x48 系统指令  0x41//4级亮度 8段显示 显示开
//	GN1650_Wrt_RAM(0x6A,LEDENCODE[value/100%10] | LEDDOT);
//	GN1650_Wrt_RAM(0x6C,LEDENCODE[value/10%10]);
//	GN1650_Wrt_RAM(0x6E,LEDENCODE[value%10]); //low	
}
/********** 数码管无显示 **********/
void  GN1650_display_D(void)	
{
	GN1650_Wrt_RAM(0x48,0x00);
}

/**********  IIC初始化 *********/
void i2c_init(void)
{
	 /* enable GPIOB clock */
	 rcu_periph_clock_enable(RCU_GPIOB);
	 /* enable I2C0 clock */
	 rcu_periph_clock_enable(RCU_I2C0);
	
	 /* connect PB6 to I2C0_SCL */
	 gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_6);
	 /* connect PB7 to I2C0_SDA */
	 gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_7);
	
	 gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_6);//PB6_42  I2C0_SCL 
	 gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_6);
	
	 gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_7);//PB7_43  I2C0_SDA
	 gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
			
	 /* configure I2C0 clock */
	 //i2c_clock_config(I2C0,60000,I2C_DTCY_2);

	 /* enable I2C0 */
	 i2c_enable(I2C0);
	 /* enable acknowledge */
	 i2c_ack_config(I2C0,I2C_I2CMODE_ENABLE);
	 
	 /*  空闲状态 */
	 gpio_bit_write(GPIOB,GPIO_PIN_6,1);
	 gpio_bit_write(GPIOB,GPIO_PIN_7,1);
	 
	 GN1650_Wrt_RAM(0x48,0x00);//关闭显示
	 	
}
void SDA_Rx(void)					//主机recv from 从机
{
	 /* enable GPIOB clock */
	 rcu_periph_clock_enable(RCU_GPIOB);
	 gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
	
}
void SDA_Tx(void)
{
	 /* enable GPIOB clock */
	 rcu_periph_clock_enable(RCU_GPIOB);
	 gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_7);//PB7_43  I2C0_SDA
	 gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
}

void IIC_SCL(uint8_t n)
{
	gpio_bit_write(GPIOB,GPIO_PIN_6,n);
}
void IIC_SDA(uint8_t n)
{
	gpio_bit_write(GPIOB,GPIO_PIN_7,n);
}

static void IIC_Delay(void)
{
	__IO  uint16_t cnt=1;
	while(cnt--);
}

/*********************模拟IIC通信****************/
/*
*函数功能:IIC起始
*提    示:
*输入参数:无
*输出参数:无
*返回值  :无
*/
static void IIC_Start1(void)
{
	SDA_Tx();
	//2、SCL 1
	IIC_SCL(1);
	//3、SDA 1
	IIC_SDA(1);
	//延时5us
	IIC_Delay();
	//4、SCL 0 
	IIC_SDA(0);
	//延时5us
	IIC_Delay();
	//5、SDA 0
	IIC_SCL(0);
	//延时5us
	IIC_Delay();		
}
/*
*函数功能:IIC结束
*提    示:
*输入参数:无
*输出参数:无
*返回值  :无
*/

static void IIC_Stop1(void)
{
	//2、SCL 1
	IIC_SCL(1);
	//3、SDA 0
	IIC_SDA(0);
	//延时5us
	IIC_Delay();
	//4、SDA 1
	IIC_SDA(1);
	//延时5us
	IIC_Delay();
}

/*
*函数功能:IIC应答
*提    示:
*输入参数:无
*输出参数:无
*返回值  :无
*/
void IIC_ACK(void)
{	
	SDA_Rx();
	IIC_SCL(0);
	IIC_Delay(); 
	IIC_SDA(0); 	
	IIC_Delay();     
	IIC_SCL(1);
	IIC_Delay();                  
	IIC_SCL(0);                     
	IIC_Delay();
	SDA_Tx(); 
	IIC_SDA(0);	
	IIC_Delay();
		
}

/****************模拟IIC通信**************/

/* 描述:一个字节数据发送函数               
 * 参数:  无
 * 返回值:无		*/

void IIC_Wrt_Byte(uint8_t data)
{
	int i;	
    IIC_SCL(0);    //拉低时钟开始数据传输
	for(i = 0;i < 8;i++)
	{
		IIC_SDA((data & 0x80)>0 ); //check bit7
        data <<= 1; 	  
		IIC_Delay();   //这三个延时都是必须的
		IIC_SCL(1);
		IIC_Delay(); 
		IIC_SCL(0);	
		IIC_Delay();	
	}	
}

/* 描述:一个字节数据接收函数               
 * 参数:  无
 * 返回值:接收到的字节数据		*/

uint8_t IIC_Rev_Byte(void)
{
	uint8_t dat=0;
	uint8_t i;	
 
	SDA_Rx();			/* 设置数据线为输入方式 */
	IIC_Delay();                    
	for(i = 0;i < 8;i++)
	{  
		IIC_SCL(0);		/* 设置时钟线为低,准备接收数据位	*/
		IIC_Delay();               
		IIC_SCL(1);		/* 设置时钟线为高使数据线上数据有效  */              
		if(READ_SDA) dat|=0x80;	//同ret++; /* 读数据位,接收的数据位放入ret中 */
		dat>>=1;
		IIC_Delay();
	}
	IIC_SCL(0); 
 	
	return dat;
}

// write to RAM
void GN1650_Wrt_RAM(uint8_t Address, uint8_t Data)
{
	IIC_Start1();
    IIC_Wrt_Byte(Address);
    IIC_ACK();
    IIC_Wrt_Byte(Data);
    IIC_ACK();
    IIC_Stop1();	
}
/********** 按键扫描函数 get 按键 ID **********/
uint8_t GetKey(void)
{
	uint8_t key=0;
	
	IIC_Start1();
	IIC_Wrt_Byte(0x49);
	IIC_ACK();
	key= IIC_Rev_Byte();
	IIC_ACK();
	IIC_Stop1();
	return key;
}

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

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

相关文章

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--大模型、扩散模型、视觉导航

专属领域论文订阅 VX 扫嘛关注{晓理紫}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 分类: 大语言模型LLM视觉模型VLM扩散模型视觉导航具身智能&#xff0c;机器人强化学习开放词汇&#xff0c;检测分割 [晓理紫]每日论…

六、数组(1)一维数组

所谓数组&#xff0c;就是一个集合&#xff0c;里面存放了相同类型的数据元素 特点1&#xff1a;数组中每个数据元素都是相同的数据类型 特点2&#xff1a;数组是由连续的内存位置组成的 一、一维数组的定义方式 1、数据类型 数组名[数组长度]; 2、数据类型 数组名[数组长度…

谷歌浏览器通过network模拟HTTP中的GET/POST请求获取response

1、F12打开network选中需要模拟的方法Copy->Copy as fetch 2、通过AI帮你进行转换一下调用格式 原代码 fetch("https://mp.amap.com/api/forward/aggregate?mtop.alsc.kbt.intergration.toolkit.call.queryCallBlockInfo", {"headers": {"acce…

Latex绘图

排查Latex报错 “Command \csubfigure already defined” 这个可以通过添加如下命令&#xff1a; \usepackage{subfig} \usepackage{subfloat} ..... \begin{figure*}[h] \centering \subfloat[subfloat title]{ \label{fig:subfig:a} \includegraphics[scale0.7]{Figs/.....…

python-基础篇-函数

文章目录 函数基础目标01. 函数的快速体验1.1 快速体验 02. 函数基本使用2.1 函数的定义2.2 函数调用2.3 第一个函数演练思考 2.4 PyCharm 的调试工具2.5 函数的文档注释 03. 函数的参数3.1 函数参数的使用3.2 参数的作用3.3 形参和实参 04. 函数的返回值05. 函数的嵌套调用函数…

Spring RabbitMQ那些事(3-消息可靠传输和订阅)

目录 一、序言二、生产者确保消息发送成功1、为什么需要Publisher Confirms2、哪些消息会被确认处理成功 三、消费者保证消息被处理四、Spring RabbitMQ支持代码示例1、 application.yml2、RabbigtMQ配置3、可靠生产者配置4、可靠消费者配置5、测试用例 一、序言 在有些业务场…

VisualSVN Server实战

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;下载VisualSVN Server&#xff08;二&#xff09;安装VisualSVN Server&#xff08;三&#xff09;使用VisualSVN Server1、新建仓库&#xff08;1&#xff09;新建Repository&#xff08;2&#xff09;选择仓库类…

Python 折线图的绘制(Seaborn篇-04)

Python 折线图的绘制(Seaborn篇-04)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

基于python socket实现TCP/UDP通信

两个应用程序如果需要进行通讯最基本的一个前提就是能够唯一的标示一个进程&#xff0c;我们知道IP层的ip地址可以唯一标示主机&#xff0c;而TCP层协议和端口号可以唯一标示主机的一个进程&#xff0c;这样我们可以利用ip地址&#xff0b;协议&#xff0b;端口号唯一标示网络中…

论文阅读_CogTree_推理的认知树

英文名称: From Complex to Simple: Unraveling the Cognitive Tree for Reasoning with Small Language Models中文名称: 从复杂到简单&#xff1a;揭示小型语言模型推理的认知树链接: http://arxiv.org/abs/2311.06754v1代码: https://github.com/alibaba/EasyNLP作者: Junbi…

深入解析 JavaScript 中的 setTimeout() 和 setInterval()

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 setTimeout() 和 setInterval() 是 JavaScript 中非常常用的定时函数…

Django从入门到精通(一)

目录 一、Django环境搭建与命令 1.1、安装 1.2、命令行 创建项目 编写代码 运行 app概念 1.3、Pycharm创建项目 1.4、虚拟环境 创建虚拟环境 - 命令行 介绍 操作 基本问题 Pycharm 项目虚拟环境 django虚拟环境【安装django最新版本】 django虚拟环境【安装指…

frida https抓包

web端导入证书、https代理即可解决大部分需求&#xff0c;但是&#xff0c;有些app需要处理ssl pinning验证。 废话不多说。frida处理ssl pin的步骤大体如下。 安装python3.x,并在python环境中安装frida&#xff1a; pip install frida pip install frida-tools下载frida-se…

【设计模式】你知道游戏SL大法是什么设计模式吗?

什么是备忘录模式&#xff1f; 老规矩&#xff0c;我们先来看看备忘录模式 (Memento) 的定义&#xff1a;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 它的UML类图如下&a…

Django(八)

1. 管理员操作 1.1 添加 from django.shortcuts import render, redirectfrom app01 import models from app01.utils.pagination import Paginationfrom django import forms from django.core.exceptions import ValidationError from app01.utils.bootstrap import BootStr…

【MySQL】where和having的区别

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;数据库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 用途: 使用位置: 操作对象: 聚合函数: 示例&#xff1a; 结语 我的其他博客 前言 数据库中的 WHERE 和 HAVING 子句在 SQL 查…

排序算法整理

快速排序 C实现 void fastStore(int *a, int start, int end){if(start>end)return ;int leftstart;int rightend;int tempa[left];//设置基准值tempwhile(left < right) //左指针的位置一定小于右指针的位置{while(a[right]>temp && left < right) //左…

RabbitMQ-消息延迟

一、死信交换机 1、描述 一个队列接收到的消息有过期时间&#xff0c;消息过期之后&#xff0c;如果配置有死信队列&#xff0c;消息就会进去死信队列。 2、图解 3、过程 当生产者将消息发送到exchange1&#xff0c;然后交换机将消息路由到队列queue1&#xff0c;但是队列que…

快速入门:使用 Gemini Embeddings 和 Elasticsearch 进行向量搜索

Gemini 是 Google DeepMind 开发的多模态大语言模型家族&#xff0c;作为 LaMDA 和 PaLM 2 的后继者。由 Gemini Ultra、Gemini Pro 和 Gemini Nano 组成&#xff0c;于 2023 年 12 月 6 日发布&#xff0c;定位为 OpenAI 的竞争者 GPT-4。 本教程演示如何使用 Gemini API 创建…

浅析Java中volatile关键字

认识volatile关键字 Java中的volatile关键字用于修饰一个变量&#xff0c;当这个变量被多个线程共享时&#xff0c;这个变量的值如果发生更新&#xff0c;每个线程都能获取到最新的值。volatile关键字在多线程环境下还会禁止指令重排序&#xff0c;确保变量的赋值操作按照代码的…