void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //ʹÄÜGPIOBʱÖÓ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //ÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_2); //PB6,PB7 Êä³ö¸ß GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ; //¸¡¿ÕÊäÈë GPIO_Init(GPIOA, &GPIO_InitStructure); }改为stm32g070xx单片机中的代码引用stm32g0xx中hal并显示头文件

时间: 2023-08-16 21:03:42 浏览: 124
#include "stm32g0xx_hal.h" void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; __HAL_RCC_GPIOB_CLK_ENABLE(); //ʹÄÜGPIOBʱÖÓ __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStructure.Pin = GPIO_PIN_10|GPIO_PIN_2; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP ; //ÍÆÍìÊä³ö GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10|GPIO_PIN_2,GPIO_PIN_SET); //PB6,PB7 Êä³ö¸ß GPIO_InitStructure.Pin = GPIO_PIN_7; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; //¸¡¿ÕÊäÈë GPIO_InitStructure.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); }
相关问题

void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); } 根据这段代码判断一下用的内部时钟还是外部时钟

根据提供的代码,无法直接判断使用的是内部时钟还是外部时钟。代码中只涉及到了GPIO口的初始化和配置,并没有直接涉及时钟源的选择。 要确定使用的是内部时钟还是外部时钟,需要查看代码中的其他部分或者相关的时钟初始化函数。例如,通过调用RCC函数库中的函数来配置和选择系统时钟源。 在这段代码中,可以看到通过调用`RCC_APB2PeriphClockCmd()`函数来使能GPIOB端口的时钟,但这只是使能GPIOB端口的时钟,与系统时钟源无关。 因此,单凭这段代码无法准确判断使用的是内部时钟还是外部时钟。需要进一步查看代码中的其他部分来确定时钟源的选择。

void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); } 这一段代码可以实现初始化的功能吗?是否启用上拉电阻?

这段代码实现了 I2C 初始化的功能,但没有启用上拉电阻。 在这段代码中,GPIOB 的引脚 6 和 7 被配置为开漏输出模式。GPIO_Mode_Out_OD 表示开漏输出模式,它允许引脚在逻辑高电平时处于高阻态。GPIO_SetBits() 函数将引脚置为高电平。 然而,这段代码没有显示地启用上拉电阻。在 I2C 通信中,上拉电阻对于保持信号线在空闲状态时保持高电平是很重要的。如果没有上拉电阻,信号线可能会漂移到低电平,从而导致通信错误。 要启用上拉电阻,你需要在 GPIO_Init() 函数中将 GPIO_InitStructure.GPIO_Mode 设置为 GPIO_Mode_IPU。这将启用上拉输入模式。具体来说,你可以将以下代码添加到 I2C_Init() 函数中: ```c GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入模式 GPIO_Init(GPIOB, &GPIO_InitStructure); ``` 这样可以确保引脚在空闲状态时保持高电平,提高 I2C 通信的可靠性。请根据实际情况进行相应的修改和调整。
阅读全文

相关推荐

#include "stm32f10x.h" #include "oled.h" void IIC_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE ); //PB6--SCL PB7--SDL GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_DeInit(I2C1); I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 400000; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_OwnAddress1 = 0x30; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); } void I2C_WriteByte(uint8_t addr,uint8_t data) { while( I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //检查IIC总线是否繁忙 I2C_GenerateSTART(I2C1, ENABLE); //开启IIC,发送起始信号 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5主模式 I2C_Send7bitAddress(I2C1, OLED_ADDRESS , I2C_Direction_Transmitter); //发送OLED地址 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查EV6 I2C_SendData(I2C1, addr); //发送寄存器地址 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); I2C_SendData(I2C1, data); //发送数据 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); I2C_GenerateSTOP(I2C1, ENABLE); }

#include "./iic/iic.h" /******************************************************************************* * 函 数 名: IIC_Init * 函数功能: IIC初始化 * 输 入: 无 * 输 出: 无 *******************************************************************************/ void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC|IIC_SDA_PORT_RCC,ENABLE); GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure); IIC_SCL = 1; IIC_SDA = 1; } /******************************************************************************* * 函 数 名 : SDA_OUT * 函数功能 : SDA输出配置 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void SDA_OUT(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure); } /******************************************************************************* * 函 数 名 : SDA_IN * 函数功能 : SDA输入配置 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void SDA_IN(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure); } /******************************************************************************* * 函 数 名 : IIC_Start * 函数功能 : 产生IIC起始信号 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA = 1; IIC_SCL = 1; delay_us(5); IIC_SDA = 0;//START:when CLK is high,DATA change form high to low delay_us(6); IIC_SCL = 0;//钳住I2C总线,准备发送或接收数据 }怎么让不同的IIC设备都能够复用整套模拟IIC代码,不重复造车轮

#include "stm32f10x.h" // Device header #include "TCS34725_IIC.h" #include "Delay.h" /* 接线方法 VCC→3.3V/5V GND→GND SCL→PB10 SDA→PB11 */ #define IIC_D 6 void TCS34725_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN | IIC_SCL_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); } void SDA_Pin_IN(void) //SDA输入 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// GPIO_Init(GPIOB, &GPIO_InitStructure); } void SDA_Pin_Output(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); } void TCS34725_IIC_Delay() { Delay_us(IIC_D); } /* *@brief IIC总线初始化函数 *@param[in] NULL *@author MrWeng *@date 2020-8-10 */ void TCS34725_IIC_Init(void) { IIC_SDA_H;//释放IIC总线的数据线。 IIC_SCL_H;//释放IIC总线的时钟线。 TCS34725_IIC_Delay(); } /**************************************************************** 通讯起始信号:当 SCL 线是高电平时 SDA 线从高电平向低电平切换,表示通讯的开始; *****************************************************************/ void TCS34725_IIC_start(void) { IIC_SDA_H;//拉高 IIC_SCL_H; TCS34725_IIC_Delay(); IIC_SDA_L; IIC_SCL_L; //拉低时钟线,准备开始时钟 TCS34725_IIC_Delay(); } /**************************************************************** 通讯停止信号:当 SCL 是高电平时 SDA线由低电平向高电平切换,表示通讯的停止。 *****************************************************************/ void TCS34725_IIC_stop(void) { IIC_SCL_H; IIC_SDA_L; TCS34725_IIC_Delay(); IIC_SDA_H; //通讯停止 IIC_SCL_L; TCS34725_IIC_Delay(); } /**************************************************************** //接收应答信号函数 *****************************************************************/ uint8_t TCS34725_IIC_Get_ack(void) { uint16_t CNT; SDA_Pin_IN(); IIC_SCL_L; //拉低时钟线。 IIC_SCL_H; //拉高时钟线。 TCS34725_IIC_Delay(); while((IIC_SDA_Read) && (CNT < 100) ) { CNT++; if(CNT == 100) { return 0; } } IIC_SCL_L; //拉低时钟线。 TCS34725_IIC_Delay(); SDA_Pin_Output(); return 1; } /**************************************************************** //发送应答信号函数 *****************************************************************/ void TCS34725_IIC_ACK(void) { IIC_SDA_L; //拉低数据线,应答 IIC_SCL_H; //产生第九个时钟信号。 TCS34725_IIC_Delay(); IIC_SCL_L; TCS34725_IIC_Delay(); } //非应答 void TCS34725_IIC_NACK(void) { IIC_SDA_H; //拉高数据线,非应答 IIC_SCL_H; //产生第九个时钟信号。 TCS34725_IIC_Delay(); IIC_SCL_L; } /**************************************************************** //向IIC总线写入一个字节的数据 *****************************************************************/ void TCS34725_IIC_write_byte(uint8_t Data) { uint8_t i; for(i=0;i<8;i++)//八位数据 { if((Data & 0x80) == 0x80) { IIC_SDA_H; } else { IIC_SDA_L; } IIC_SCL_H; //一个时钟信号送入数据 TCS34725_IIC_Delay(); IIC_SCL_L; TCS34725_IIC_Delay(); Data = Data << 1;//数据左移一位,把次高位放在最高位,为写入次高位做准备 } IIC_SDA_L; //应答处理前拉低,跳过应答 } /**************************************************************** //从IIC总线读取一个字节的数据函数 *****************************************************************/ uint8_t TCS34725_IIC_read_byte(void) { uint8_t i; uint8_t Data = 0; //定义一个缓冲寄存器。 SDA_Pin_IN(); IIC_SCL_L; //先拉低时钟线 IIC_SDA_H; //再拉高数据线 TCS34725_IIC_Delay(); for(i = 0;i < 8;i++) { Data = Data<<1; //将缓冲字节的数据左移一位,准备读取数据。 IIC_SCL_H; //拉高时钟线,开始读取下一位数据 TCS34725_IIC_Delay(); if(IIC_SDA_Read) //如果数据线为高平电平。 { Data = Data|0x01; //则给缓冲字节的最低位写1。 } IIC_SCL_L; //拉低时钟线,一位读取完成 TCS34725_IIC_Delay(); } SDA_Pin_Output(); return Data; //返回读取的一个字节数据。 } 分析该tcs34725代码是否出错

根据这段代码帮我写一下OLED运行的流程图#ifndef __OLED_I2C_H #define __OLED_I2C_H #include "stm32f10x.h" #include "SysTick.h" #define OLED_ADDRESS 0x78 //默认0x78 //定义IIC总线连接的GPIO端口, 用户只需要修改下面代码即可任意改变SCL和SDA的引脚 #define OLED_SCL PBout(6) //SCL引脚 #define OLED_SDA PBout(7) //SDA引脚 #define OLED_SCL_GPIO_PORT GPIOB /* GPIO端口 */ #define OLED_SCL_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define OLED_SCL_PIN GPIO_Pin_6 /* 连接到SCL时钟线的GPIO */ #define OLED_SDA_GPIO_PORT GPIOB /* GPIO端口 */ #define OLED_SDA_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define OLED_SDA_PIN GPIO_Pin_7 /* 连接到SDA数据线的GPIO */ #define OLED_IIC_SDA_READ() GPIO_ReadInputDataBit(OLED_SDA_GPIO_PORT, OLED_SDA_PIN) /* 读SDA口线状态 */ extern unsigned int HZ; unsigned int GB16_NUM(void); void OLED_IIC_GPIO_Config(void); void OLED_IIC_Start(void); void OLED_IIC_Stop(void); uint8_t OLED_IIC_WaitAck(void); void OLED_Write_IIC_Byte(uint8_t _ucByte); void OLED_Write_IIC_Command(u8 IIC_Command); void OLED_Fill(u8 fill_Data); void OLED_Set_Pos(u8 x, u8 y); void OLED_ON(void); void OLED_OFF(void); void OLED_Clear(void); void OLED_ShowChar(u8 x, u8 y, u8 chr); void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len,u8 mode); void OLED_ShowCH(u8 x, u8 y,u8 *chs); void OLED_Init(void); void OLED_DrawBMP(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]); void OLED_ShowStr6x8(char x,char y, char ch[]); #endif 和#include "OLED_I2C.h" #include "SysTick.h" #include "codetab.h" #include "string.h" unsigned int HZ=0; //返回GB16字库里汉字个数 unsigned int GB16_NUM(void) { unsigned int HZ_NUM; unsigned char *PT; PT = hz_index; while(*PT++ != '\0') { HZ_NUM++; } return HZ_NUM/2; } void OLED_IIC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(OLED_SCL_RCC|OLED_SDA_RCC, ENABLE); /* 打开GPIO时钟 */ GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出 */ GPIO_Init(OLED_SCL_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN; GPIO_Init(OLED_SDA_GPIO_PORT, &GPIO_InitStructure); /* 给一个停止信号, 复位IIC总线上的所有设备到待机模式 */ OLED_IIC_Stop(); } static void OLED_IIC_Delay(void) { uint8_t i; /*  下面的时间是通过逻辑分析仪测试得到的。 工作条件:CPU主频72MHz ,MDK编译环境,1级优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us */ for (i = 0; i < 10; i++); } /* ********************************************************************************************************* * 函 数 名: IIC_Start * 功能说明: CPU发起IIC总线启动信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void OLED_IIC_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示IIC总线启动信号 */ OLED_SDA=1; OLED_SCL=1; OLED_IIC_Delay(); OLED_SDA=0; OLED_IIC_Delay(); OLED_SCL=0; OLED_IIC_Delay(); } /* ********************************************************************************************************* * 函 数 名: IIC_Start * 功能说明: CPU发起IIC总线停止信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void OLED_IIC_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示IIC总线停止信号 */ OLED_SDA=0; OLED_SCL=1; OLED_IIC_Delay(); OLED_SDA=1; } /* ********************************************************************************************************* * 函 数 名: IIC_WaitAck * 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号 * 形 参:无 * 返 回 值: 返回0表示正确应答,1表示无器件响应 ********************************************************************************************************* */ uint8_t OLED_IIC_WaitAck(void) { uint8_t re; OLED_SDA=1; /* CPU释放SDA总线 */ OLED_IIC_Delay(); OLED_SCL=1; /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ OLED_IIC_Delay(); if (OLED_IIC_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } OLED_SCL=0; OLED_IIC_Delay(); return re; } //向IIC总线写数据 void OLED_Write_IIC_Byte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { OLED_SDA=1; } else { OLED_SDA=0; } OLED_IIC_Delay(); OLED_SCL=1; OLED_IIC_Delay(); OLED_SCL=0; if (i == 7) { OLED_SDA=1; // 释放总线 } _ucByte <<= 1; /* 左移一个bit */ OLED_IIC_Delay(); } } //写命令 void OLED_Write_IIC_Command(u8 IIC_Command) { OLED_IIC_Start(); OLED_Write_IIC_Byte(OLED_ADDRESS);//OLED地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(0x00);//寄存器地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(IIC_Command); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } //写数据 void OLED_Write_IIC_Data(u8 IIC_Data) { OLED_IIC_Start(); OLED_Write_IIC_Byte(OLED_ADDRESS);//OLED地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(0x40);//寄存器地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(IIC_Data); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } //OLED全屏填充 void OLED_Fill(u8 fill_Data) { u8 m,n; for(m=0;m<8;m++) { OLED_Write_IIC_Command(0xb0+m); //page0-page1 OLED_Write_IIC_Command(0x00); //low column start address OLED_Write_IIC_Command(0x10); //high column start address for(n=0;n<130;n++) { OLED_Write_IIC_Data(fill_Data); } } } //设置起始点坐标 void OLED_Set_Pos(u8 x, u8 y) { OLED_Write_IIC_Command(0xb0+y); OLED_Write_IIC_Command((((x+2)&0xf0)>>4)|0x10); OLED_Write_IIC_Command(((x+2)&0x0f)|0x01); } //将OLED从休眠中唤醒 void OLED_ON(void) { OLED_Write_IIC_Command(0X8D); //设置电荷泵 OLED_Write_IIC_Command(0X14); //开启电荷泵 OLED_Write_IIC_Command(0XAF); //OLED唤醒 } //让OLED休眠 -- 休眠模式下,OLED功耗不到10uA void OLED_OFF(void) { OLED_Write_IIC_Command(0X8D); //设置电荷泵 OLED_Write_IIC_Command(0X10); //关闭电荷泵 OLED_Write_IIC_Command(0XAE); //OLED休眠 } //清屏 void OLED_Clear(void) { OLED_Fill(0x00); } //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 void OLED_ShowChar(u8 x, u8 y, u8 chr) { u8 c = 0, i = 0; c = chr - ' '; //得到偏移后的值 if(x > 130 - 1) { x = 0; y = y + 2; } OLED_Set_Pos(x, y); for(i = 0; i < 8; i++) OLED_Write_IIC_Data(zf[c * 16 + i]); OLED_Set_Pos(x, y + 1); for(i = 0; i < 8; i++) OLED_Write_IIC_Data(zf[c * 16 + i + 8]); } //m^n函数 u32 oled_pow(u8 m, u8 n) { u32 result = 1; while(n--)result *= m; return result; } //显示个数字 //x,y :起点坐标 //len :数字的位数 //num:数值(0~4294967295); //mode: 为1:显示0 为0:显示空格 void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len,u8 mode) { u8 t, temp; for(t = 0; t < len; t++) { temp = (num / oled_pow(10, len - t - 1)) % 10; if(temp == 0) { if(mode) OLED_ShowChar(x + 8*t, y, '0'); else OLED_ShowChar(x + 8*t, y, ' '); continue; } else OLED_ShowChar(x + 8*t, y, temp + '0'); } } //显示中英文字符 void OLED_ShowCH(u8 x, u8 y,u8 *chs) { u32 i=0; u32 j; char* m; while (*chs != '\0') { if (*chs > 0xa0) //汉字内码都是大于0xa0 { for (i=0 ;i < HZ;i++) { if(x>112) { x=0; y=y+2; } if ((*chs == hz_index[i*2]) && (*(chs+1) == hz_index[i*2+1])) { OLED_Set_Pos(x, y); for(j=0;j<16;j++) OLED_Write_IIC_Data(hz[i*32+j]); OLED_Set_Pos(x,y+1); for(j=0;j<16;j++) OLED_Write_IIC_Data(hz[i*32+j+16]); x +=16; break; } } chs+=2; } else { if(x>122) { x=0; y=y+2; } m=strchr(zf_index,*chs); if (m!=NULL) { OLED_Set_Pos(x, y); for(j = 0; j < 8; j++) OLED_Write_IIC_Data(zf[((u8)*m-' ') * 16 + j]); OLED_Set_Pos(x, y + 1); for(j = 0; j < 8; j++) OLED_Write_IIC_Data(zf[((u8)*m-' ') * 16 + j + 8]); x += 8; } chs++; } } } void OLED_ShowStr6x8(char x,char y, char ch[]) { char TextSize=1; char c = 0,i = 0,j = 0; switch(TextSize) { case 1: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 126) { x = 0; y++; } OLED_Set_Pos(x,y); for(i=0;i<6;i++) OLED_Write_IIC_Data(F6x8[c][i]); x += 6; j++; } }break; } } //初始化SSD1306 void OLED_Init(void) { HZ= GB16_NUM(); OLED_IIC_GPIO_Config(); OLED_Write_IIC_Command(0xAE); //--display off OLED_Write_IIC_Command(0x00); //---set low column address OLED_Write_IIC_Command(0x10); //---set high column address OLED_Write_IIC_Command(0x40); //--set start line address OLED_Write_IIC_Command(0xB0); //--set page address OLED_Write_IIC_Command(0x81); // contract control OLED_Write_IIC_Command(0xFF); //--128 OLED_Write_IIC_Command(0xA1); //set segment remap OLED_Write_IIC_Command(0xA6); //--normal / reverse OLED_Write_IIC_Command(0xA8); //--set multiplex ratio(1 to 64) OLED_Write_IIC_Command(0x3F); //--1/32 duty OLED_Write_IIC_Command(0xC8); //Com scan direction OLED_Write_IIC_Command(0xD3); //-set display offset OLED_Write_IIC_Command(0x00); // OLED_Write_IIC_Command(0xD5); //set osc division OLED_Write_IIC_Command(0x80); // OLED_Write_IIC_Command(0xD8); //set area color mode off OLED_Write_IIC_Command(0x05); // OLED_Write_IIC_Command(0xD9); //Set Pre-Charge Period OLED_Write_IIC_Command(0xF1); // OLED_Write_IIC_Command(0xDA); //set com pin configuartion OLED_Write_IIC_Command(0x12); // OLED_Write_IIC_Command(0xDB); //set Vcomh OLED_Write_IIC_Command(0x30); // OLED_Write_IIC_Command(0x8D); //set charge pump enable OLED_Write_IIC_Command(0x14); // OLED_Write_IIC_Command(0xAF); //--turn on oled panel } // x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8) void OLED_DrawBMP(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]) { u16 j=0; u8 x,y; if(y1%8==0) y = y1/8; else y = y1/8 + 1; for(y=y0;y<y1;y++) { OLED_Set_Pos(x0,y); for(x=x0;x<x1;x++) { OLED_Write_IIC_Data(BMP[j++]); } } }

最新推荐

recommend-type

(完整版)网络大集体备课的心得与体会(最新整理).pdf

(完整版)网络大集体备课的心得与体会(最新整理).pdf
recommend-type

2.2-导数的基本公式与运算法则省名师优质课赛课获奖课件.ppt

2.2-导数的基本公式与运算法则省名师优质课赛课获奖课件.ppt
recommend-type

098L产品网络推广策略.pptx

098L产品网络推广策略.pptx
recommend-type

前端分析-202307110078988

前端分析-202307110078988
recommend-type

1.1.1算法的概念(一).doc

1.1.1算法的概念(一).doc
recommend-type

构建基于ajax, jsp, Hibernate的博客网站源码解析

根据提供的文件信息,本篇内容将专注于解释和阐述ajax、jsp、Hibernate以及构建博客网站的相关知识点。 ### AJAX AJAX(Asynchronous JavaScript and XML)是一种用于创建快速动态网页的技术,它允许网页在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。AJAX的核心是JavaScript中的XMLHttpRequest对象,通过这个对象,JavaScript可以异步地向服务器请求数据。此外,现代AJAX开发中,常常用到jQuery中的$.ajax()方法,因为其简化了AJAX请求的处理过程。 AJAX的特点主要包括: - 异步性:用户操作与数据传输是异步进行的,不会影响用户体验。 - 局部更新:只更新需要更新的内容,而不是整个页面,提高了数据交互效率。 - 前后端分离:AJAX技术允许前后端分离开发,让前端开发者专注于界面和用户体验,后端开发者专注于业务逻辑和数据处理。 ### JSP JSP(Java Server Pages)是一种动态网页技术标准,它允许开发者将Java代码嵌入到HTML页面中,从而实现动态内容的生成。JSP页面在服务器端执行,并将生成的HTML发送到客户端浏览器。JSP是Java EE(Java Platform, Enterprise Edition)的一部分。 JSP的基本工作原理: - 当客户端首次请求JSP页面时,服务器会将JSP文件转换为Servlet。 - 服务器上的JSP容器(如Apache Tomcat)负责编译并执行转换后的Servlet。 - Servlet生成HTML内容,并发送给客户端浏览器。 JSP页面中常见的元素包括: - 指令(Directives):如page、include、taglib等。 - 脚本元素:脚本声明(Script declarations)、脚本表达式(Scriptlet)和脚本片段(Expression)。 - 标准动作:如jsp:useBean、jsp:setProperty、jsp:getProperty等。 - 注释:在客户端浏览器中不可见的注释。 ### Hibernate Hibernate是一个开源的对象关系映射(ORM)框架,它提供了从Java对象到数据库表的映射,简化了数据库编程。通过Hibernate,开发者可以将Java对象持久化到数据库中,并从数据库中检索它们,而无需直接编写SQL语句或掌握复杂的JDBC编程。 Hibernate的主要优点包括: - ORM映射:将对象模型映射到关系型数据库的表结构。 - 缓存机制:提供了二级缓存,优化数据访问性能。 - 数据查询:提供HQL(Hibernate Query Language)和Criteria API等查询方式。 - 延迟加载:可以配置对象或对象集合的延迟加载,以提高性能。 ### 博客网站开发 构建一个博客网站涉及到前端页面设计、后端逻辑处理、数据库设计等多个方面。使用ajax、jsp、Hibernate技术栈,开发者可以更高效地构建功能完备的博客系统。 #### 前端页面设计 前端主要通过HTML、CSS和JavaScript来实现,其中ajax技术可以用来异步获取文章内容、用户评论等,无需刷新页面即可更新内容。 #### 后端逻辑处理 JSP可以在服务器端动态生成HTML内容,根据用户请求和数据库中的数据渲染页面。Hibernate作为ORM框架,可以处理Java对象与数据库表之间的映射,并提供数据库的CRUD(创建、读取、更新、删除)操作。 #### 数据库设计 博客网站的数据库设计通常包含多个表,如用户表(存储用户信息)、文章表(存储文章信息)、评论表(存储用户评论信息)等。使用Hibernate框架可以简化数据库操作,同时确保数据的一致性和安全性。 #### 安全性和性能优化 安全性是构建网站时需要考虑的重要方面,包括但不限于SQL注入防护、XSS攻击防护、会话管理等。性能优化方面,可以利用Hibernate的缓存机制,以及对JSP页面和ajax请求进行适当的缓存处理。 ### 结论 ajax、jsp、Hibernate技术结合可以构建出高效、动态、易于维护的博客网站。在开发过程中,应当关注前后端分离、用户体验优化、系统性能和安全性等关键要素,确保博客网站的稳定和长期可用性。通过本篇文章,读者应该已经对这些技术有了初步了解,并能够结合文件提供的源码开始进行相关开发实践。
recommend-type

【Unity Sunny Land关卡设计高级指南】:打造完美关卡的8大技巧

# 1. Unity关卡设计概述 ## 1.1 关卡设计的核心要素 关卡设计作为游戏开发中不可或缺的一环,承担着构建游戏世界、呈现故事背景、引导玩家体验和激发玩家兴趣的责任。一个优秀的关卡不仅需要有吸引人的视觉效果和有趣的挑战,还需平衡玩家体验,提供连贯的游戏故事。 ## 1.2 关卡设计师的角色 在Unity引擎的环境下,关卡设计师需要具备对场景布局、角色互动、剧情
recommend-type

C++ 模版

<think>我们正在讨论C++模板的使用和常见问题。根据用户要求,所有行内数学表达式使用$...$,独立公式使用$$...$$,用中文回答,并生成相关问题。同时,回答要结构清晰,帮助用户逐步解决问题。 首先,回顾用户的问题:用户想了解C++模板的使用和常见问题。我们将从以下几个方面展开: 1. 模板的基本概念和用途 2. 函数模板和类模板 3. 模板特化和偏特化 4. 模板元编程简介 5. 常见问题及解决方案 注意:在回答中,我们会引用站内提供的引用内容(引用[1]和引用[2])作为参考,但主要围绕模板展开。 ### 1. 模板的基本概念和用途 C++模板是一种支持泛型编程的特性,允许
recommend-type

C#随机数摇奖系统功能及隐藏开关揭秘

### C#摇奖系统知识点梳理 #### 1. C#语言基础 C#(发音为“看井”)是由微软开发的一种面向对象的、类型安全的编程语言。它是.NET框架的核心语言之一,广泛用于开发Windows应用程序、ASP.NET网站、Web服务等。C#提供丰富的数据类型、控制结构和异常处理机制,这使得它在构建复杂应用程序时具有很强的表达能力。 #### 2. 随机数的生成 在编程中,随机数生成是常见的需求之一,尤其在需要模拟抽奖、游戏等场景时。C#提供了System.Random类来生成随机数。Random类的实例可以生成一个伪随机数序列,这些数在统计学上被认为是随机的,但它们是由确定的算法生成,因此每次运行程序时产生的随机数序列相同,除非改变种子值。 ```csharp using System; class Program { static void Main() { Random rand = new Random(); for(int i = 0; i < 10; i++) { Console.WriteLine(rand.Next(1, 101)); // 生成1到100之间的随机数 } } } ``` #### 3. 摇奖系统设计 摇奖系统通常需要以下功能: - 用户界面:显示摇奖结果的界面。 - 随机数生成:用于确定摇奖结果的随机数。 - 动画效果:模拟摇奖的视觉效果。 - 奖项管理:定义摇奖中可能获得的奖品。 - 规则设置:定义摇奖规则,比如中奖概率等。 在C#中,可以使用Windows Forms或WPF技术构建用户界面,并集成上述功能以创建一个完整的摇奖系统。 #### 4. 暗藏的开关(隐藏控制) 标题中提到的“暗藏的开关”通常是指在程序中实现的一个不易被察觉的控制逻辑,用于在特定条件下改变程序的行为。在摇奖系统中,这样的开关可能用于控制中奖的概率、启动或停止摇奖、强制显示特定的结果等。 #### 5. 测试 对于摇奖系统来说,测试是一个非常重要的环节。测试可以确保程序按照预期工作,随机数生成器的随机性符合要求,用户界面友好,以及隐藏的控制逻辑不会被轻易发现或利用。测试可能包括单元测试、集成测试、压力测试等多个方面。 #### 6. System.Random类的局限性 System.Random虽然方便使用,但也有其局限性。其生成的随机数序列具有一定的周期性,并且如果使用不当(例如使用相同的种子创建多个实例),可能会导致生成相同的随机数序列。在安全性要求较高的场合,如密码学应用,推荐使用更加安全的随机数生成方式,比如RNGCryptoServiceProvider。 #### 7. Windows Forms技术 Windows Forms是.NET框架中用于创建图形用户界面应用程序的库。它提供了一套丰富的控件,如按钮、文本框、标签等,以及它们的事件处理机制,允许开发者设计出视觉效果良好且功能丰富的桌面应用程序。 #### 8. WPF技术 WPF(Windows Presentation Foundation)是.NET框架中用于构建桌面应用程序用户界面的另一种技术。与Windows Forms相比,WPF提供了更现代化的控件集,支持更复杂的布局和样式,以及3D图形和动画效果。WPF的XAML标记语言允许开发者以声明性的方式设计用户界面,与C#代码分离,易于维护和更新。 #### 9. 压缩包子文件TransBallDemo分析 从文件名“TransBallDemo”可以推测,这可能是一个C#的示例程序或者演示程序,其中“TransBall”可能表示旋转的球体,暗示该程序包含了动画效果,可能是用来模拟转动的球体(如转盘或摇奖球)。该文件可能是用来展示如何实现一个带有视觉动画效果的摇奖系统的C#程序。 总结以上内容,我们可以得出构建一个C#摇奖系统需要深入理解C#语言及其随机数生成机制,设计用户界面,集成动画效果,确保隐藏控制逻辑的安全性,以及全面测试系统以保证其正确性和公平性。通过掌握Windows Forms或WPF技术,可以进一步增强系统的视觉和交互体验。
recommend-type

【数据驱动的力量】:管道缺陷判别方法论与实践经验

# 摘要 数据驱动技术在管道缺陷检测领域展现出强大的力量,本文首先概述了数据驱动的力量和管道缺陷判别的基础理论。接着,重点探讨了管道缺陷的类型与特征、数据采集与预处理、数据驱动模型的选择与构建。在实践技巧章节,本文详述了实战数据集的准备与处理、缺陷识别算法的应用、以及性能评估与模型优化。此外,高级应用章节深入讨论了实时数据处理分析、多模态数据融合技术、以及深度学习在缺