完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
亮灯 初始化对应IO #define LEDPORT GPIOB //定义IO接口 #define LED1 GPIO_Pin_0 //定义IO接口 #define LED2 GPIO_Pin_1 //定义IO接口 oid LED_Init(void){ //LED灯的接口初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = LED1 | LED2; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(LEDPORT, &GPIO_InitStructure); } 按键 #define KEYPORT GPIOB //定义IO接口组 #define KEY1 GPIO_Pin_2 //定义IO接口 void KEY_Init(void){ //微动开关的接口初始化 GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = KEY1; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻 // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(KEYPORT,&GPIO_InitStructure); } /* 选择IO接口工作方式: GPIO_Mode_AIN 模拟输入 GPIO_Mode_IN_FLOATING 浮空输入 GPIO_Mode_IPD 下拉输入 GPIO_Mode_IPU 上拉输入 GPIO_Mode_Out_PP 推挽输出 GPIO_Mode_Out_OD 开漏输出 GPIO_Mode_AF_PP 复用推挽输出 GPIO_Mode_AF_OD 复用开漏输出 */ Flash读写 //FLASH写入数据 void FLASH_W(u32 add,u16 dat){ //参数1:32位FLASH地址。参数2:16位数据 // RCC_HSICmd(ENABLE); //打开HSI时钟 FLASH_Unlock(); //解锁FLASH编程擦除控制器 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_ErasePage(add); //擦除指定地址页 FLASH_ProgramHalfWord(add,dat); //从指定页的addr地址开始写 FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位 FLASH_Lock(); //锁定FLASH编程擦除控制器 } //FLASH读出数据 u16 FLASH_R(u32 add){ //参数1:32位读出FLASH地址。返回值:16位数据 u16 a; a = *(u16*)(add);//从指定页的addr地址开始读 return a; } USART串口收发 #define USART1_REC_LEN 200 //定义USART1最大接收字节数 #define USART2_REC_LEN 200 //定义USART2最大接收字节数 #define USART3_REC_LEN 200 //定义USART3最大接收字节数 //不使用某个串口时要禁止此串口,以减少编译量 #define EN_USART1 1 //使能(1)/禁止(0)串口1 #define EN_USART2 0 //使能(1)/禁止(0)串口2 #define EN_USART3 0 //使能(1)/禁止(0)串口3 extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u16 USART1_RX_STA; //接收状态标记 extern u16 USART2_RX_STA; //接收状态标记 extern u16 USART3_RX_STA; //接收状态标记 //函数声明 void USART1_Init(u32 bound);//串口1初始化并启动 void USART2_Init(u32 bound);//串口2初始化并启动 void USART3_Init(u32 bound);//串口3初始化并启动 void USART1_printf(char* fmt,...); //串口1的专用printf函数 void USART2_printf(char* fmt,...); //串口2的专用printf函数 void USART3_printf(char* fmt,...); //串口3的专用printf函数 //使UASRT串口可用printf函数发送 //在usart.h文件里可更换使用printf函数的串口号 #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 _sys_exit(int x){ x = x; } //重定义fputc函数 int fputc(int ch, FILE *f){ while((USART_n->SR&0X40)==0);//循环发送,直到发送完毕 USART_n->DR = (u8) ch; return ch; } #endif /* USART1串口相关程序 */ #if EN_USART1 //USART1使用与屏蔽选择 u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART1_RX_STA=0; //接收状态标记 /* USART1专用的printf函数 当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数 调用方法:USART1_printf("123"); //向USART2发送字符123 */ void USART1_printf (char *fmt, ...){ char buffer[USART1_REC_LEN+1]; // 数据长度 u8 i = 0; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr); while ((i < USART1_REC_LEN) && (i < strlen(buffer))){ USART_SendData(USART1, (u8) buffer[i++]); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); } va_end(arg_ptr); } void USART1_Init(u32 bound){ //串口1初始化并启动 //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX PA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断 USART_Cmd(USART1, ENABLE); //使能串口 } void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改) u8 Res; //以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是数据的长度(不包括回车) //当(USART1_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。 //在主函数里写判断if(USART1_RX_STA&0xC000),然后读USART1_RX_BUF[]数组,读到0x0d 0x0a即是结束。 //注意在主函数处理完串口数据后,要将USART1_RX_STA清0 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾) Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑 if((USART1_RX_STA&0x8000)==0){//接收未完成 if(USART1_RX_STA&0x4000){//接收到了0x0d if(Res!=0x0a)USART1_RX_STA=0;//接收错误,重新开始 else USART1_RX_STA|=0x8000; //接收完成了 }else{ //还没收到0X0D if(Res==0x0d)USART1_RX_STA|=0x4000; else{ USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组 USART1_RX_STA++; //数据长度计数加1 if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收 } } } } } #endif /* USART2串口相关程序 */ #if EN_USART2 //USART2使用与屏蔽选择 u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART2_RX_STA=0; //接收状态标记 /* USART2专用的printf函数 当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数 调用方法:USART2_printf("123"); //向USART2发送字符123 */ void USART2_printf (char *fmt, ...){ char buffer[USART2_REC_LEN+1]; // 数据长度 u8 i = 0; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf(buffer, USART2_REC_LEN+1, fmt, arg_ptr); while ((i < USART2_REC_LEN) && (i < strlen(buffer))){ USART_SendData(USART2, (u8) buffer[i++]); while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); } va_end(arg_ptr); } void USART2_Init(u32 bound){ //串口1初始化并启动 //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能UART2所在GPIOA的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能串口的RCC时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //设置USART2的RX接口是PA3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //设置USART2的TX接口是PA2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //USART2 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART2, &USART_InitStructure); //初始化串口 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断 USART_Cmd(USART2, ENABLE); //使能串口 //Usart2 NVIC 配置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } void USART2_IRQHandler(void){ //串口2中断服务程序(固定的函数名不能修改) u8 Res; //以下是字符串接收到USART2_RX_BUF[]的程序,(USART2_RX_STA&0x3FFF)是数据的长度(不包括回车) //当(USART2_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。 //在主函数里写判断if(USART2_RX_STA&0xC000),然后读USART2_RX_BUF[]数组,读到0x0d 0x0a即是结束。 //注意在主函数处理完串口数据后,要将USART2_RX_STA清0 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾) Res =USART_ReceiveData(USART2);//(USART1->DR); //读取接收到的数据 printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑 if((USART2_RX_STA&0x8000)==0){//接收未完成 if(USART2_RX_STA&0x4000){//接收到了0x0d if(Res!=0x0a)USART2_RX_STA=0;//接收错误,重新开始 else USART2_RX_STA|=0x8000; //接收完成了 }else{ //还没收到0X0D if(Res==0x0d)USART2_RX_STA|=0x4000; else{ USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组 USART2_RX_STA++; //数据长度计数加1 if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收 } } } } } #endif #if EN_USART3 //如果使能了接收 u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART3_RX_STA=0; //接收状态标记 /* USART3专用的printf函数 当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数 调用方法:USART3_printf("123"); //向USART3发送字符123 */ void USART3_printf (char *fmt, ...){ char buffer[USART3_REC_LEN+1]; // 数据长度 u8 i = 0; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf(buffer, USART3_REC_LEN+1, fmt, arg_ptr); while ((i < USART3_REC_LEN) && (i < strlen(buffer))){ USART_SendData(USART3, (u8) buffer[i++]); while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); } va_end(arg_ptr); } void USART3_Init(u32 BaudRate){ //USART3初始化并启动 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //使能UART3所在GPIOB的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能串口的RCC时钟 //串口使用的GPIO口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//设置USART3的RX接口是PB11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//接口模式 浮空输入 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//设置USART3的TX接口是PB10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//接口模式 复用推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); //配置串口 USART_InitStructure.USART_BaudRate = BaudRate; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART3, &USART_InitStructure);//配置串口3 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//使能串口接收中断 //USART_ITConfig(USART3, USART_IT_TXE, ENABLE);//串口发送中断在发送数据时开启 USART_Cmd(USART3, ENABLE);//使能串口3 //串口中断配置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//允许USART3中断 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//中断等级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } //串口3中断服务程序(固定的函数名不能修改) //调用方法:if(USART3_RX_STA&0xC000){ 加入数据处理程序 }//标志位是0xC000表示收到数据串完成。 void USART3_IRQHandler(void){ u8 Res; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){ //接收中断 Res =USART_ReceiveData(USART3);//读取接收到的数据 if(Res=='S'){//判断数据是否是STOP(省略读取S) USART3_RX_STA=1;//如果是STOP则标志位为1 }else if(Res=='K'){//判断数据是否是OK(省略读取K) USART3_RX_STA=2;//如果是OK则标志位为2 } } } #endif RS485驱动 485用的是Usart(TTL)信号转换的 void RS485_Init(void){ //RS485接口初始化 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = RS485_RE; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(RS485PORT, &GPIO_InitStructure); GPIO_ResetBits(RS485PORT,RS485_RE); //RE端控制接收/发送状态,RE为1时发送,为0时接收。 } /* RS485总线通信,使用USART3,这是RS485专用的printf函数 调用方法:RS485_printf("123"); //向USART3发送字符123 */ void RS485_printf (char *fmt, ...){ char buffer[USART3_REC_LEN+1]; // 数据长度 u8 i = 0; va_list arg_ptr; GPIO_SetBits(RS485PORT,RS485_RE); //为高电平(发送)//RS485收发选择线 va_start(arg_ptr, fmt); vsnprintf(buffer, USART3_REC_LEN+1, fmt, arg_ptr); while ((i < USART3_REC_LEN) && (i < strlen(buffer))){ USART_SendData(USART3, (u8) buffer[i++]); while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); } va_end(arg_ptr); GPIO_ResetBits(RS485PORT,RS485_RE); //为低电平(接收)//RS485收发选择线 } I²C通讯 #define HostAddress 0xc0 //总线主机的器件地址 #define BusSpeed 200000 //总线速度(不高于400000) void I2C_GPIO_Init(void){ //I2C接口初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //启动I2C功能 GPIO_InitStructure.GPIO_Pin = I2C_SCL | I2C_SDA; //选择端口号 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //选择IO接口工作方式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(I2CPORT, &GPIO_InitStructure); } void I2C_Configuration(void){ //I2C初始化 I2C_InitTypeDef I2C_InitStructure; I2C_GPIO_Init(); //先设置GPIO接口的状态 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//设置为I2C模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = HostAddress; //主机地址(从机不得用此地址) I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//允许应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //7位地址模式 I2C_InitStructure.I2C_ClockSpeed = BusSpeed; //总线速度设置 I2C_Init(I2C1,&I2C_InitStructure); I2C_Cmd(I2C1,ENABLE);//开启I2C } void I2C_SAND_BUFFER(u8 SlaveAddr,u8 WriteAddr,u8* pBuffer,u16 NumByteToWrite){ //I2C发送数据串(器件地址,寄存器,内部地址,数量) I2C_GenerateSTART(I2C1,ENABLE);//产生起始位 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //清除EV5 I2C_Send7bitAddress(I2C1,SlaveAddr,I2C_Direction_Transmitter);//发送器件地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//清除EV6 I2C_SendData(I2C1,WriteAddr); //内部功能地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));//移位寄存器非空,数据寄存器已空,产生EV8,发送数据到DR既清除该事件 while(NumByteToWrite--){ //循环发送数据 I2C_SendData(I2C1,*pBuffer); //发送数据 pBuffer++; //数据指针移位 while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));//清除EV8 } I2C_GenerateSTOP(I2C1,ENABLE);//产生停止信号 } void I2C_SAND_BYTE(u8 SlaveAddr,u8 writeAddr,u8 pBuffer){ //I2C发送一个字节(从地址,内部地址,内容) I2C_GenerateSTART(I2C1,ENABLE); //发送开始信号 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //等待完成 I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter); //发送从器件地址及状态(写入) while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //等待完成 I2C_SendData(I2C1,writeAddr); //发送从器件内部寄存器地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待完成 I2C_SendData(I2C1,pBuffer); //发送要写入的内容 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待完成 I2C_GenerateSTOP(I2C1,ENABLE); //发送结束信号 } void I2C_READ_BUFFER(u8 SlaveAddr,u8 readAddr,u8* pBuffer,u16 NumByteToRead){ //I2C读取数据串(器件地址,寄存器,内部地址,数量) while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1,ENABLE);//开启信号 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //清除 EV5 I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter); //写入器件地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//清除 EV6 I2C_Cmd(I2C1,ENABLE); I2C_SendData(I2C1,readAddr); //发送读的地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //清除 EV8 I2C_GenerateSTART(I2C1,ENABLE); //开启信号 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //清除 EV5 I2C_Send7bitAddress(I2C1,SlaveAddr,I2C_Direction_Receiver); //将器件地址传出,主机为读 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //清除EV6 while(NumByteToRead){ if(NumByteToRead == 1){ //只剩下最后一个数据时进入 if 语句 I2C_AcknowledgeConfig(I2C1,DISABLE); //最后有一个数据时关闭应答位 I2C_GenerateSTOP(I2C1,ENABLE); //最后一个数据时使能停止位 } if(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){ //读取数据 *pBuffer = I2C_ReceiveData(I2C1);//调用库函数将数据取出到 pBuffer pBuffer++; //指针移位 NumByteToRead--; //字节数减 1 } } I2C_AcknowledgeConfig(I2C1,ENABLE); } u8 I2C_READ_BYTE(u8 SlaveAddr,u8 readAddr){ //I2C读取一个字节 u8 a; while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1,ENABLE); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_Cmd(I2C1,ENABLE); I2C_SendData(I2C1,readAddr); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTART(I2C1,ENABLE); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1,SlaveAddr, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); I2C_AcknowledgeConfig(I2C1,DISABLE); //最后有一个数据时关闭应答位 I2C_GenerateSTOP(I2C1,ENABLE); //最后一个数据时使能停止位 a = I2C_ReceiveData(I2C1); return a; } RTC走时 /* //时间读写与设置说明// 1,在mani函数开头放入RTC_Config();就可以使能时钟了。 在RTC_Config();函数中自带判断是不是首次使用RTC 2,使用 RTC_Get();读出时间。读出的数据存放在: 年 ryear (16位) 月 rmon (以下都是8位) 日 rday 时 rhour 分 rmin 秒 rsec 周 rweek 3,使用 RTC_Set(4位年,2位月,2位日,2位时,2位分,2位秒); 写入时间。例如:RTC_Get(2017,08,06,21,34,00); 其他函数都是帮助如上3个函数的,不需要调用。 注意要使用RTC_Get和RTC_Set的返回值,为0时表示读写正确。 */ #include "sys.h" #include "rtc.h" //以下2条全局变量--用于RTC时间的读取 u16 ryear; //4位年 u8 rmon,rday,rhour,rmin,rsec,rweek;//2位月日时分秒周 void RTC_First_Config(void){ //首次启用RTC的设置 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//启用PWR和BKP的时钟(from APB1) PWR_BackupAccessCmd(ENABLE);//后备域解锁 BKP_DeInit();//备份寄存器模块复位 RCC_LSEConfig(RCC_LSE_ON);//外部32.768KHZ晶振开启 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//等待稳定 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTC时钟源配置成LSE(外部低速晶振32.768KHZ) RCC_RTCCLKCmd(ENABLE);//RTC开启 RTC_WaitForSynchro();//开启后需要等待APB1时钟与RTC时钟同步,才能读写寄存器 RTC_WaitForLastTask();//读写寄存器前,要确定上一个操作已经结束 RTC_SetPrescaler(32767);//设置RTC分频器,使RTC时钟为1Hz,RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) RTC_WaitForLastTask();//等待寄存器写入完成 //当不使用RTC秒中断,可以屏蔽下面2条 // RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断 // RTC_WaitForLastTask();//等待写入完成 } void RTC_Config(void){ //实时时钟初始化 //在BKP的后备寄存器1中,存了一个特殊字符0xA5A5 //第一次上电或后备电源掉电后,该寄存器数据丢失,表明RTC数据丢失,需要重新配置 if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){//判断寄存数据是否丢失 RTC_First_Config();//重新配置RTC BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5 }else{ //若后备寄存器没有掉电,则无需重新配置RTC //这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型 if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){ //这是上电复位 } else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){ //这是外部RST管脚复位 } RCC_ClearFlag();//清除RCC中复位标志 //虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行 //但是每次上电后,还是要使能RTCCLK RCC_RTCCLKCmd(ENABLE);//使能RTCCLK RTC_WaitForSynchro();//等待RTC时钟与APB1时钟同步 //当不使用RTC秒中断,可以屏蔽下面2条 // RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断 // RTC_WaitForLastTask();//等待操作完成 } #ifdef RTCClockOutput_Enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_TamperPinCmd(DISABLE); BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock); #endif } void RTC_IRQHandler(void){ //RTC时钟1秒触发中断函数(名称固定不可修改) if (RTC_GetITStatus(RTC_IT_SEC) != RESET){ } RTC_ClearITPendingBit(RTC_IT_SEC); RTC_WaitForLastTask(); } void RTCAlarm_IRQHandler(void){ //闹钟中断处理(启用时必须调高其优先级) if(RTC_GetITStatus(RTC_IT_ALR) != RESET){ } RTC_ClearITPendingBit(RTC_IT_ALR); RTC_WaitForLastTask(); } //判断是否是闰年函数 //月份 1 2 3 4 5 6 7 8 9 10 11 12 //闰年 31 29 31 30 31 30 31 31 30 31 30 31 //非闰年 31 28 31 30 31 30 31 31 30 31 30 31 //输入:年份 //输出:该年份是不是闰年.1,是.0,不是 u8 Is_Leap_Year(u16 year){ if(year%4==0){ //必须能被4整除 if(year%100==0){ if(year%400==0)return 1;//如果以00结尾,还要能被400整除 else return 0; }else return 1; }else return 0; } //设置时钟 //把输入的时钟转换为秒钟 //以1970年1月1日为基准 //1970~2099年为合法年份 //月份数据表 u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表 const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的月份日期表 //写入时间 u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec){ //写入当前时间(1970~2099年有效), u16 t; u32 seccount=0; if(syear<2000||syear>2099)return 1;//syear范围1970-2099,此处设置范围为2000-2099 for(t=1970;t else seccount+=31536000; //平年的秒钟数 } smon-=1; for(t=0;t if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数 } seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 seccount+=(u32)hour*3600;//小时秒钟数 seccount+=(u32)min*60; //分钟秒钟数 seccount+=sec;//最后的秒钟加上去 RTC_First_Config(); //重新初始化时钟 BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5 RTC_SetCounter(seccount);//把换算好的计数器值写入 RTC_WaitForLastTask(); //等待写入完成 return 0; //返回值:0,成功;其他:错误代码. } //读出时间 u8 RTC_Get(void){//读出当前时间值 //返回值:0,成功;其他:错误代码. static u16 daycnt=0; u32 timecount=0; u32 temp=0; u16 temp1=0; timecount=RTC_GetCounter(); temp=timecount/86400; //得到天数(秒钟数对应的) if(daycnt!=temp){//超过一天了 daycnt=temp; temp1=1970; //从1970年开始 while(temp>=365){ if(Is_Leap_Year(temp1)){//是闰年 if(temp>=366)temp-=366;//闰年的秒钟数 else {temp1++;break;} } else temp-=365; //平年 temp1++; } ryear=temp1;//得到年份 temp1=0; while(temp>=28){//超过了一个月 if(Is_Leap_Year(ryear)&&temp1==1){//当年是不是闰年/2月份 if(temp>=29)temp-=29;//闰年的秒钟数 else break; }else{ if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年 else break; } temp1++; } rmon=temp1+1;//得到月份 rday=temp+1; //得到日期 } temp=timecount%86400; //得到秒钟数 rhour=temp/3600; //小时 rmin=(temp%3600)/60; //分钟 rsec=(temp%3600)%60; //秒钟 rweek=RTC_Get_Week(ryear,rmon,rday);//获取星期 return 0; } u8 RTC_Get_Week(u16 year,u8 month,u8 day){ //按年月日计算星期(只允许1901-2099年)//已由RTC_Get调用 u16 temp2; u8 yearH,yearL; yearH=year/100; yearL=year%100; // 如果为21世纪,年份数加100 if (yearH>19)yearL+=100; // 所过闰年数只算1900年之后的 temp2=yearL+yearL/4; temp2=temp2%7; temp2=temp2+day+table_week[month-1]; if (yearL%4==0&&month<3)temp2--; return(temp2%7); //返回星期值 } MID音乐 void BUZZER_Init(void){ //蜂鸣器的接口初始化 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = BUZZER; //选择端口号 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(BUZZERPORT, &GPIO_InitStructure); GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1 } void BUZZER_BEEP1(void){ //蜂鸣器响一声 u16 i; for(i=0;i<200;i++){ GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鸣器接口输出0 delay_us(500); //延时 GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1 delay_us(500); //延时 } } uc16 music1[78]={ //音乐1的数据表(奇数是音调,偶数是长度) 330,750, 440,375, 494,375, 523,750, 587,375, 659,375, 587,750, 494,375, 392,375, 440,1500, 330,750, 440,375, 494,375, 523,750, 587,375, 659,375, 587,750, 494,375, 392,375, 784,1500, 659,750, 698,375, 784,375, 880,750, 784,375, 698,375, 659,750, 587,750, 659,750, 523,375, 494,375, 440,750, 440,375, 494,375, 523,750, 523,750, 494,750, 392,750, 440,3000 }; void MIDI_PLAY(void){ //MIDI音乐 u16 i,e; for(i=0;i<39;i++){ for(e=0;e delay_us(500000/music1[i*2]); //延时 GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1 delay_us(500000/music1[i*2]); //延时 } } } TM1640驱动数码管 #define DEL 1 //宏定义 通信速率(默认为1,如不能通信可加大数值) //地址模式的设置 //#define TM1640MEDO_ADD 0x40 //宏定义 自动加一模式 #define TM1640MEDO_ADD 0x44 //宏定义 固定地址模式(推荐) //显示亮度的设置 //#define TM1640MEDO_DISPLAY 0x88 //宏定义 亮度 最小 //#define TM1640MEDO_DISPLAY 0x89 //宏定义 亮度 //#define TM1640MEDO_DISPLAY 0x8a //宏定义 亮度 //#define TM1640MEDO_DISPLAY 0x8b //宏定义 亮度 #define TM1640MEDO_DISPLAY 0x8c //宏定义 亮度(推荐) //#define TM1640MEDO_DISPLAY 0x8d //宏定义 亮度 //#define TM1640MEDO_DISPLAY 0x8f //宏定义 亮度 最大 #define TM1640MEDO_DISPLAY_OFF 0x80 //宏定义 亮度 关 void TM1640_start(){ //通信时序 启始(基础GPIO操作)(低层) GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(1)); //接口输出高电平1 GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(1)); //接口输出高电平1 delay_us(DEL); GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(0)); //接口输出0 delay_us(DEL); GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(0)); //接口输出0 delay_us(DEL); } void TM1640_stop(){ //通信时序 结束(基础GPIO操作)(低层) GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(0)); //接口输出0 GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(1)); //接口输出高电平1 delay_us(DEL); GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(1)); //接口输出高电平1 delay_us(DEL); } void TM1640_write(u8 date){ //写数据(低层) u8 i; u8 aa; aa=date; GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(0)); //接口输出0 GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(0)); //接口输出0 for(i=0;i<8;i++){ GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(0)); //接口输出0 delay_us(DEL); if(aa&0x01){ GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(1)); //接口输出高电平1 delay_us(DEL); }else{ GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(0)); //接口输出0 delay_us(DEL); } GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(1)); //接口输出高电平1 delay_us(DEL); aa=aa>>1; } GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(0)); //接口输出0 GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(0)); //接口输出0 } void TM1640_Init(void){ //TM1640接口初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = TM1640_DIN | TM1640_SCLK; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(TM1640_GPIOPORT, &GPIO_InitStructure); GPIO_WriteBit(TM1640_GPIOPORT,TM1640_DIN,(BitAction)(1)); //接口输出高电平1 GPIO_WriteBit(TM1640_GPIOPORT,TM1640_SCLK,(BitAction)(1)); //接口输出高电平1 TM1640_start(); TM1640_write(TM1640MEDO_ADD); //设置数据,0x40,0x44分别对应地址自动加一和固定地址模式 TM1640_stop(); TM1640_start(); TM1640_write(TM1640MEDO_DISPLAY); //控制显示,开显示,0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f分别对应脉冲宽度为: //------------------1/16, 2/16, 4/16, 10/16, 11/16, 12/16, 13/16, 14/16 //0x80关显示 TM1640_stop(); } void TM1640_led(u8 date){ //固定地址模式的显示输出8个LED控制 TM1640_start(); TM1640_write(TM1640_LEDPORT); //传显示数据对应的地址 TM1640_write(date); //传1BYTE显示数据 TM1640_stop(); } void TM1640_display(u8 address,u8 date){ //固定地址模式的显示输出 const u8 buff[21]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//数字0~9及0~9加点显示段码表 //--------------- 0 1 2 3 4 5 6 7 8 9 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 无 TM1640_start(); TM1640_write(0xC0+address); //传显示数据对应的地址 TM1640_write(buff[date]); //传1BYTE显示数据 TM1640_stop(); } void TM1640_display_add(u8 address,u8 date){ //地址自动加一模式的显示输出 u8 i; const u8 buff[21]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//数字0~9及0~9加点显示段码表 //--------------- 0 1 2 3 4 5 6 7 8 9 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 无 TM1640_start(); TM1640_write(0xC0+address); //设置起始地址 for(i=0;i<16;i++){ TM1640_write(buff[date]); } TM1640_stop(); } 旋转编码器驱动 u8 KUP;//旋钮锁死标志(1为锁死) u16 cou; void ENCODER_Init(void){ //接口初始化 GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = ENCODER_L | ENCODER_D; //选择端口号 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻 GPIO_Init(ENCODER_PORT_A,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ENCODER_R; //选择端口号 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻 GPIO_Init(ENCODER_PORT_B,&GPIO_InitStructure); } u8 ENCODER_READ(void){ //接口初始化 u8 a;//存放按键的值 u8 kt; a=0; if(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L))KUP=0; //判断旋钮是否解除锁死 if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&KUP==0){ //判断是否旋转旋钮,同时判断是否有旋钮锁死 delay_us(100); kt=GPIO_ReadInputDataBit(ENCODER_PORT_B,ENCODER_R); //把旋钮另一端电平状态记录 delay_ms(3); //延时 if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)){ //去抖 if(kt==0){ //用另一端判断左或右旋转 a=1;//右转 }else{ a=2;//左转 } cou=0; //初始锁死判断计数器 while(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&cou<60000){ //等待放开旋钮,同时累加判断锁死 cou++;KUP=1;delay_us(20); // } } } if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)&&KUP==0){ //判断旋钮是否按下 delay_ms(20); if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)){ //去抖动 a=3;//在按键按下时加上按键的状态值 //while(ENCODER_D==0); 等等旋钮放开 } } return a; } LM75A温度感应器驱动 //读出LM75A的温度值(-55~125摄氏度) //温度正负号(0正1负),温度整数,温度小数(点后2位)依次放入*Tempbuffer(十进制) void LM75A_GetTemp(u8 *Tempbuffer){ u8 buf[2]; //温度值储存 u8 t=0,a=0; I2C_READ_BUFFER(LM75A_ADD,0x00,buf,2); //读出温度值(器件地址,子地址,数据储存器,字节数) t = buf[0]; //处理温度整数部分,0~125度 *Tempbuffer = 0; //温度值为正值 if(t & 0x80){ //判断温度是否是负(MSB表示温度符号) *Tempbuffer = 1; //温度值为负值 t = ~t; t++; //计算补码(原码取反后加1) } if(t & 0x01){ a=a+1; } //从高到低按位加入温度积加值(0~125) if(t & 0x02){ a=a+2; } if(t & 0x04){ a=a+4; } if(t & 0x08){ a=a+8; } if(t & 0x10){ a=a+16; } if(t & 0x20){ a=a+32; } if(t & 0x40){ a=a+64; } Tempbuffer++; *Tempbuffer = a; a = 0; t = buf[1]; //处理小数部分,取0.125精度的前2位(12、25、37、50、62、75、87) if(t & 0x20){ a=a+12; } if(t & 0x40){ a=a+25; } if(t & 0x80){ a=a+50; } Tempbuffer++; *Tempbuffer = a; } //LM75进入掉电模式,再次调用LM75A_GetTemp();即可正常工作 //建议只在需要低功耗情况下使用 void LM75A_POWERDOWN(void){// I2C_SAND_BYTE(LM75A_ADD,0x01,1); // } OLED0561驱动 字库自备 #define OLED0561_ADD 0x78 // OLED的I2C地址(禁止修改) #define COM 0x00 // OLED 指令(禁止修改) #define DAT 0x40 // OLED 数据(禁止修改) void OLED0561_Init (void){//OLED屏开显示初始化 // OLED_DISPLAY_OFF(); //OLED关显示 OLED_DISPLAY_CLEAR(); //清空屏幕内容 OLED_DISPLAY_ON(); //OLED屏初始值设置并开显示 } void OLED_DISPLAY_ON (void){//OLED屏初始值设置并开显示 u8 buf[28]={ 0xae,//0xae:关显示,0xaf:开显示 0x00,0x10,//开始地址(双字节) 0xd5,0x80,//显示时钟频率? 0xa8,0x3f,//复用率? 0xd3,0x00,//显示偏移? 0XB0,//写入页位置(0xB0~7) 0x40,//显示开始线 0x8d,0x14,//VCC电源 0xa1,//设置段重新映射? 0xc8,//COM输出方式? 0xda,0x12,//COM输出方式? 0x81,0xff,//对比度,指令:0x81,数据:0~255(255最高) 0xd9,0xf1,//充电周期? 0xdb,0x30,//VCC电压输出 0x20,0x00,//水平寻址设置 0xa4,//0xa4:正常显示,0xa5:整体点亮 0xa6,//0xa6:正常显示,0xa7:反色显示 0xaf//0xae:关显示,0xaf:开显示 }; // I2C_SAND_BUFFER(OLED0561_ADD,COM,buf,28); } void OLED_DISPLAY_OFF (void){//OLED屏关显示 u8 buf[3]={ 0xae,//0xae:关显示,0xaf:开显示 0x8d,0x10,//VCC电源 }; // I2C_SAND_BUFFER(OLED0561_ADD,COM,buf,3); } void OLED_DISPLAY_LIT (u8 x){//OLED屏亮度设置(0~255) I2C_SAND_BYTE(OLED0561_ADD,COM,0x81); I2C_SAND_BYTE(OLED0561_ADD,COM,x);//亮度值 } void OLED_DISPLAY_CLEAR(void){//清屏操作 u8 j,t; for(t=0xB0;t<0xB8;t++){ //设置起始页地址为0xB0 I2C_SAND_BYTE(OLED0561_ADD,COM,t); //页地址(从0xB0到0xB7) I2C_SAND_BYTE(OLED0561_ADD,COM,0x10); //起始列地址的高4位 I2C_SAND_BYTE(OLED0561_ADD,COM,0x00); //起始列地址的低4位 for(j=0;j<132;j++){ //整页内容填充 I2C_SAND_BYTE(OLED0561_ADD,DAT,0x00); } } } //显示英文与数字8*16的ASCII码 //取模大小为16*16,取模方式为“从左到右从上到下”“纵向8点下高位” void OLED_DISPLAY_8x16(u8 x, //显示汉字的页坐标(从0到7)(此处不可修改) u8 y, //显示汉字的列坐标(从0到63) u16 w){ //要显示汉字的编号 u8 j,t,c=0; y=y+2; //因OLED屏的内置驱动芯片是从0x02列作为屏上最左一列,所以要加上偏移量 for(t=0;t<2;t++){ I2C_SAND_BYTE(OLED0561_ADD,COM,0xb0+x); //页地址(从0xB0到0xB7) I2C_SAND_BYTE(OLED0561_ADD,COM,y/16+0x10); //起始列地址的高4位 I2C_SAND_BYTE(OLED0561_ADD,COM,y%16); //起始列地址的低4位 for(j=0;j<8;j++){ //整页内容填充 I2C_SAND_BYTE(OLED0561_ADD,DAT,ASCII_8x16[(w*16)+c-512]);//为了和ASII表对应要减512 c++;}x++; //页地址加1 } } //向LCM发送一个字符串,长度64字符之内。 //应用:OLED_DISPLAY_8_16_BUFFER(0," DoYoung Studio"); void OLED_DISPLAY_8x16_BUFFER(u8 row,u8 *str){ u8 r=0; while(*str != ' |