Let's do 过程贴
本文将通过“系统框图、电路原理图、如何开启运行、主要参数情况、实现步骤”等方面记录开发过程中的硬件设计、软件调试、项目代码等。
流程图part
主程序流程图(方框图)
根据流程图我们首先要将所需模块进行初始化。以下是初始化部分代码:
从流程图中不难看出来,我们使用了继电器这一模块,其原因是正常的板载所能提供的输出电压最多为5V,而这并不能驱动12V的电机,于是我们采用了继电器去驱动电机。我们所使用的继电器为5VDC(5V直流电)驱动,通过继电器进而驱动电机的动作。
其模式更改采用窗口发送的方式:通过串口发送不同的字符串,当STM32F411接收到对应的字符串后,修改程序当前模式并执行对应的模式。下面是通过串口修改修改电流阈值的图片(PS:因为我这个插入视频和GIF我没做过):
下面是所用到的窗口字符串:
定时器中断流程图(方框图)
将选择后的模式功能部分放入定时器中,可以积极响应模式的要求并快速运行的运行,以下是定时器的内部代码:
关键逻辑交互图
以下为各个模块代码部分展示
GPIO.c
void OLED_MAP() { OLED_ShowChiness(1,1,13); OLED_ShowChiness(1,3,0); OLED_ShowChiness(1,5,1); OLED_ShowChiness(1,7,2); OLED_ShowChiness(1,9,3); OLED_ShowChiness(1,11,4); OLED_ShowChiness(1,13,5); OLED_ShowChiness(1,15,6); OLED_ShowChiness(2,1,7); OLED_ShowChiness(2,3,8); OLED_ShowChiness(3,1,9); OLED_ShowChiness(3,3,10); OLED_ShowChiness(4,1,11); OLED_ShowChiness(4,3,12); OLED_ShowString(2,5,": mA"); OLED_ShowString(3,5,": V"); OLED_ShowString(4,5,": W"); } void OLED_MAP2() { OLED_ShowChiness(1,1,14); OLED_ShowChiness(1,3,15); OLED_ShowChiness(1,5,16); OLED_ShowChiness(1,7,17); OLED_ShowString(1,9,":"); OLED_ShowChiness(2,1,18); OLED_ShowChiness(2,3,19); OLED_ShowChiness(2,5,20); OLED_ShowChiness(2,7,21); OLED_ShowString(2,9,":"); OLED_ShowString(2,14,"mA"); } void show_i() { short iii = INA_GET_Current_MA(); OLED_ShowSignedNum(2,7,iii,5); } void show_v() { unsigned int v = INA_GET_Voltage_MV(); OLED_ShowNum(3,7,v/1000,2); OLED_ShowChar(3,9,'.'); OLED_ShowNum(3,10,v-(v/1000)*1000,3); } void show_w() { unsigned int p = INA_GET_Power_MW()*20; OLED_ShowNum(4,7,p/1000,2); OLED_ShowChar(4,9,'.'); OLED_ShowNum(4,10,p-(p/1000)*1000,3); } void gpio_init() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Medium_Speed; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Medium_Speed; GPIO_Init(GPIOC,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOB,&GPIO_InitStruct); GPIO_WriteBit(GPIOA,GPIO_Pin_4,1); GPIO_WriteBit(GPIOB,GPIO_Pin_0,0); }
OLED.c
/*引脚配置*/ //#define OLED_W_SCL(x) GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)(x)) //#define OLED_W_SDA(x) GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)(x)) //#define lay 5 /*引脚初始化*/ void OLED_W_SCL(int x) { GPIO_WriteBit(GPIOA, GPIO_Pin_0,x); delay_us(1); } void OLED_W_SDA(int x) { GPIO_WriteBit(GPIOA, GPIO_Pin_1,x); delay_us(1); } void OLED_I2C_Init(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA, &GPIO_InitStruct); OLED_W_SCL(1); OLED_W_SDA(1); } /** * @brief I2C开始 * @param 无 * @retval 无 */ void OLED_I2C_Start(void) { OLED_W_SDA(1); OLED_W_SCL(1); OLED_W_SDA(0); OLED_W_SCL(0); } /** * @brief I2C停止 * @param 无 * @retval 无 */ void OLED_I2C_Stop(void) { OLED_W_SDA(0); OLED_W_SCL(1); OLED_W_SDA(1); } /** * @brief I2C发送一个字节 * @param Byte 要发送的一个字节 * @retval 无 */ void OLED_I2C_SendByte(uint8_t Byte) { uint8_t i; for (i = 0; i < 8; i++) { OLED_W_SDA(!!(Byte & (0x80 >> i))); OLED_W_SCL(1); OLED_W_SCL(0); } OLED_W_SCL(1); //额外的一个时钟,不处理应答信号 OLED_W_SCL(0); } /** * @brief OLED写命令 * @param Command 要写入的命令 * @retval 无 */ void OLED_WriteCommand(uint8_t Command) { OLED_I2C_Start(); OLED_I2C_SendByte(0x78); //从机地址 OLED_I2C_SendByte(0x00); //写命令 OLED_I2C_SendByte(Command); OLED_I2C_Stop(); } /** * @brief OLED写数据 * @param Data 要写入的数据 * @retval 无 */ void OLED_WriteData(uint8_t Data) { OLED_I2C_Start(); OLED_I2C_SendByte(0x78); //从机地址 OLED_I2C_SendByte(0x40); //写数据 OLED_I2C_SendByte(Data); OLED_I2C_Stop(); } /** * @brief OLED设置光标位置 * @param Y 以左上角为原点,向下方向的坐标,范围:0~7 * @param X 以左上角为原点,向右方向的坐标,范围:0~127 * @retval 无 */ void OLED_SetCursor(uint8_t Y, uint8_t X) { OLED_WriteCommand(0xB0 | Y); //设置Y位置 OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位 OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位 } /** * @brief OLED清屏 * @param 无 * @retval 无 */ void OLED_Clear(void) { uint8_t i, j; for (j = 0; j < 8; j++) { OLED_SetCursor(j, 0); for(i = 0; i < 128; i++) { OLED_WriteData(0x00); } } } /** * @brief OLED显示一个字符 * @param Line 行位置,范围:1~4 * @param Column 列位置,范围:1~16 * @param Char 要显示的一个字符,范围:ASCII可见字符 * @retval 无 */ void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char) { uint8_t i; OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分 for (i = 0; i < 8; i++) { OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容 } OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分 for (i = 0; i < 8; i++) { OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容 } } /** * @brief OLED显示一个中文 * @param Line 行位置,范围:1~4 * @param Column 列位置,范围:1~16 * @param num 要显示的一个字符地址 * @retval 无 */ void OLED_ShowChiness(uint8_t Line, uint8_t Column, uint8_t num) { uint8_t i; OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分 for (i = 0; i < 16; i++) { OLED_WriteData(OLED_Chiness_F8x16[num][i]); //显示上半部分内容 } OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分 for (i = 0; i < 16; i++) { OLED_WriteData(OLED_Chiness_F8x16[num][i + 16]); //显示下半部分内容 } } /** * @brief OLED显示字符串 * @param Line 起始行位置,范围:1~4 * @param Column 起始列位置,范围:1~16 * @param String 要显示的字符串,范围:ASCII可见字符 * @retval 无 */ void OLED_ShowString(uint8_t Line, uint8_t Column, char *String) { uint8_t i; for (i = 0; String[i] != '\0'; i++) { OLED_ShowChar(Line, Column + i, String[i]); } } /** * @brief OLED次方函数 * @retval 返回值等于X的Y次方 */ uint32_t OLED_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while (Y--) { Result *= X; } return Result; } /** * @brief OLED显示数字(十进制,正数) * @param Line 起始行位置,范围:1~4 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:0~4294967295 * @param Length 要显示数字的长度,范围:1~10 * @retval 无 */ void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0'); } } /** * @brief OLED显示数字(十进制,带符号数) * @param Line 起始行位置,范围:1~4 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:-2147483648~2147483647 * @param Length 要显示数字的长度,范围:1~10 * @retval 无 */ void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length) { uint8_t i; uint32_t Number1; if (Number >= 0) { OLED_ShowChar(Line, Column, '+'); Number1 = Number; } else { OLED_ShowChar(Line, Column, '-'); Number1 = -Number; } for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0'); } } /** * @brief OLED显示数字(十六进制,正数) * @param Line 起始行位置,范围:1~4 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:0~0xFFFFFFFF * @param Length 要显示数字的长度,范围:1~8 * @retval 无 */ void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i, SingleNumber; for (i = 0; i < Length; i++) { SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16; if (SingleNumber < 10) { OLED_ShowChar(Line, Column + i, SingleNumber + '0'); } else { OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A'); } } } /** * @brief OLED显示数字(二进制,正数) * @param Line 起始行位置,范围:1~4 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:0~1111 1111 1111 1111 * @param Length 要显示数字的长度,范围:1~16 * @retval 无 */ void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0'); } } /** * @brief OLED初始化 * @param 无 * @retval 无 */ void OLED_Init(void) { uint32_t i, j; for (i = 0; i < 1000; i++) //上电延时 { for (j = 0; j < 1000; j++); } OLED_I2C_Init(); //端口初始化 OLED_WriteCommand(0xAE); //关闭显示 OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率 OLED_WriteCommand(0x80); OLED_WriteCommand(0xA8); //设置多路复用率 OLED_WriteCommand(0x3F); OLED_WriteCommand(0xD3); //设置显示偏移 OLED_WriteCommand(0x00); OLED_WriteCommand(0x40); //设置显示开始行 OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置 OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置 OLED_WriteCommand(0xDA); //设置COM引脚硬件配置 OLED_WriteCommand(0x12); OLED_WriteCommand(0x81); //设置对比度控制 OLED_WriteCommand(0xCF); OLED_WriteCommand(0xD9); //设置预充电周期 OLED_WriteCommand(0xF1); OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别 OLED_WriteCommand(0x30); OLED_WriteCommand(0xA4); //设置整个显示打开/关闭 OLED_WriteCommand(0xA6); //设置正常/倒转显示 OLED_WriteCommand(0x8D); //设置充电泵 OLED_WriteCommand(0x14); OLED_WriteCommand(0xAF); //开启显示 OLED_Clear(); //OLED清屏 }
OLED_Font.h
#ifndef __OLED_FONT_H #define __OLED_FONT_H /*OLED字模库,宽8像素,高16像素*/ const uint8_t OLED_F8x16[][16]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00, 0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00, 0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00, 0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00, 0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00, 0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00, 0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00, 0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, 0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04, 0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, 0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00, 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00, 0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00, 0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00, 0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00, 0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00, 0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00, 0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00, 0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, 0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00, 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00, 0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00, 0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00, 0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00, 0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00, 0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00, 0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00, 0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00, 0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, 0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, 0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00, 0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, 0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00, 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00, 0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00, 0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00, 0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00, 0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08, 0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, 0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00, 0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, 0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00, 0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00, 0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00, 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08, 0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00, 0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08, 0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00, 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00, 0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00, 0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00, 0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, 0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00, 0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, 0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00, 0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, 0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18, 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, 0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00, 0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00, 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00, 0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00, 0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00, 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, 0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00, 0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00, 0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00, 0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00, 0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, 0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00, 0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00, 0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, 0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80, 0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00, 0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, 0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00, 0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02, 0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00, 0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94 }; const uint8_t OLED_Chiness_F8x16[][32]= { 0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x10, 0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00, 0x10,0x30,0x10,0x1F,0x08,0x88,0x48,0x30, 0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,/*"功",0*/ 0x00,0x14,0xA4,0x44,0x24,0x34,0xAD,0x66, 0x24,0x94,0x04,0x44,0xA4,0x14,0x00,0x00, 0x08,0x09,0x08,0x08,0x09,0x09,0x09,0xFD, 0x09,0x09,0x0B,0x08,0x08,0x09,0x08,0x00,/*"率",1*/ 0x10,0x10,0xD0,0xFF,0x90,0x50,0x20,0x50, 0x4C,0x43,0x4C,0x50,0x20,0x40,0x40,0x00, 0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x58, 0x41,0x4E,0x60,0x58,0x47,0x40,0x40,0x00,/*"检",2*/ 0x10,0x60,0x02,0x8C,0x00,0xFE,0x02,0xF2, 0x02,0xFE,0x00,0xF8,0x00,0xFF,0x00,0x00, 0x04,0x04,0x7E,0x01,0x80,0x47,0x30,0x0F, 0x10,0x27,0x00,0x47,0x80,0x7F,0x00,0x00,/*"测",3*/ 0x00,0x00,0xE0,0x9F,0x88,0x88,0x88,0x88, 0x88,0x88,0x88,0x88,0x88,0x08,0x00,0x00, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x48,0x80,0x40,0x3F,0x00,0x00,0x00,/*"与",4*/ 0x10,0x10,0x10,0xFF,0x90,0x20,0x98,0x48, 0x28,0x09,0x0E,0x28,0x48,0xA8,0x18,0x00, 0x02,0x42,0x81,0x7F,0x00,0x40,0x40,0x42, 0x42,0x42,0x7E,0x42,0x42,0x42,0x40,0x00,/*"控",5*/ 0x40,0x50,0x4E,0x48,0x48,0xFF,0x48,0x48, 0x48,0x40,0xF8,0x00,0x00,0xFF,0x00,0x00, 0x00,0x00,0x3E,0x02,0x02,0xFF,0x12,0x22, 0x1E,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,/*"制",6*/ 0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF, 0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, 0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F, 0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,/*"电",7*/ 0x10,0x60,0x02,0x8C,0x00,0x44,0x64,0x54, 0x4D,0x46,0x44,0x54,0x64,0xC4,0x04,0x00, 0x04,0x04,0x7E,0x01,0x80,0x40,0x3E,0x00, 0x00,0xFE,0x00,0x00,0x7E,0x80,0xE0,0x00,/*"流",8*/ 0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF, 0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, 0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F, 0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,/*"电",9*/ 0x00,0x00,0xFE,0x02,0x82,0x82,0x82,0x82, 0xFA,0x82,0x82,0x82,0x82,0x82,0x02,0x00, 0x80,0x60,0x1F,0x40,0x40,0x40,0x40,0x40, 0x7F,0x40,0x40,0x44,0x58,0x40,0x40,0x00,/*"压",10*/ 0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x10, 0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00, 0x10,0x30,0x10,0x1F,0x08,0x88,0x48,0x30, 0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,/*"功",11*/ 0x00,0x14,0xA4,0x44,0x24,0x34,0xAD,0x66, 0x24,0x94,0x04,0x44,0xA4,0x14,0x00,0x00, 0x08,0x09,0x08,0x08,0x09,0x09,0x09,0xFD, 0x09,0x09,0x0B,0x08,0x08,0x09,0x08,0x00,/*"率",12*/ 0x08,0xF8,0x08,0x10,0xE0,0x00,0x08,0xF8, 0x08,0x00,0x08,0xF8,0x80,0x78,0x08,0x00, 0x20,0x3F,0x20,0x10,0x0F,0x00,0x20,0x3F, 0x20,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,/*"DIY",13*/ 0x40,0x40,0x42,0xCC,0x00,0x08,0x48,0x88, 0x08,0x08,0x08,0xFF,0x08,0x08,0x08,0x00, 0x00,0x40,0x20,0x1F,0x20,0x40,0x40,0x41, 0x40,0x48,0x50,0x4F,0x40,0x40,0x40,0x00,/*"过",14*/ 0x10,0x60,0x02,0x8C,0x00,0x44,0x64,0x54, 0x4D,0x46,0x44,0x54,0x64,0xC4,0x04,0x00, 0x04,0x04,0x7E,0x01,0x80,0x40,0x3E,0x00, 0x00,0xFE,0x00,0x00,0x7E,0x80,0xE0,0x00,/*"流",15*/ 0x00,0x08,0x30,0x00,0xFF,0x20,0x20,0x20, 0x20,0xFF,0x20,0x20,0x22,0x2C,0x20,0x00, 0x04,0x04,0x02,0x01,0xFF,0x80,0x40,0x30, 0x0E,0x01,0x06,0x18,0x20,0x40,0x80,0x00,/*"状",16*/ 0x00,0x04,0x84,0x84,0x44,0x24,0x54,0x8F, 0x14,0x24,0x44,0x84,0x84,0x04,0x00,0x00, 0x41,0x39,0x00,0x00,0x3C,0x40,0x40,0x42, 0x4C,0x40,0x40,0x70,0x04,0x09,0x31,0x00,/*"态",17*/ 0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF, 0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, 0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F, 0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,/*"电",18*/ 0x10,0x60,0x02,0x8C,0x00,0x44,0x64,0x54, 0x4D,0x46,0x44,0x54,0x64,0xC4,0x04,0x00, 0x04,0x04,0x7E,0x01,0x80,0x40,0x3E,0x00, 0x00,0xFE,0x00,0x00,0x7E,0x80,0xE0,0x00,/*"流",19*/ 0x00,0xF8,0x01,0x22,0xA0,0xA2,0xA2,0x22, 0xFE,0x22,0xAA,0x32,0x02,0xFE,0x00,0x00, 0x00,0xFF,0x00,0x10,0x13,0x0A,0x4B,0x20, 0x17,0x0C,0x13,0x38,0x80,0xFF,0x00,0x00,/*"阈",20*/ 0x00,0x80,0x60,0xF8,0x07,0x04,0xE4,0xA4, 0xA4,0xBF,0xA4,0xA4,0xE4,0x04,0x00,0x00, 0x01,0x00,0x00,0xFF,0x40,0x40,0x7F,0x4A, 0x4A,0x4A,0x4A,0x4A,0x7F,0x40,0x40,0x00,/*"值",21*/ 0x00,0x02,0x02,0xC2,0x02,0x02,0x02,0xFE, 0x82,0x82,0x82,0x82,0x82,0x02,0x00,0x00, 0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x7F, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,/*"正",22*/ 0x00,0x00,0x7E,0x92,0x92,0x92,0x92,0x92, 0x92,0x92,0x92,0x9E,0x80,0xE0,0x00,0x00, 0x08,0x88,0x48,0x28,0x1E,0x08,0x08,0x08, 0x08,0x08,0xFE,0x08,0x08,0x08,0x08,0x00,/*"异",23*/ 0x20,0x18,0x08,0xEA,0xAC,0xA8,0xA8,0xAF, 0xA8,0xA8,0xAC,0xEA,0x08,0x28,0x18,0x00, 0x00,0x00,0x3E,0x02,0x02,0x02,0x02,0xFF, 0x02,0x02,0x12,0x22,0x1E,0x00,0x00,0x00,/*"常",24*/ }; #endif
INA219.c
void INA_REG_Write(unsigned char reg,unsigned int data); #ifdef INA_INSIDE_IIC void INA_IIC_Delay() {unsigned char x; for(x=1;x>0;x--) { __NOP();__NOP();__NOP();__NOP();__NOP(); } } void INA_IIC_INIT(void) //IIC初始化 { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOF时钟 //GPIOF9,F10初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//LED0和LED1对应IO口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO GPIO_SetBits(GPIOC,GPIO_Pin_2|GPIO_Pin_3);//GPIOF9,F10设置高,灯灭 } //SDA配置为输出 void INA_IIC_SDA_OUT(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOF时钟 //GPIOF9,F10初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//LED0和LED1对应IO口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO } //SDA配置为输入 void INA_IIC_SDA_IN(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOC时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100M GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC13 } //开始信号 void INA_IIC_Start(void) { IIC_SDA_H; IIC_SCL_H; INA_IIC_Delay(); IIC_SDA_L; INA_IIC_Delay(); IIC_SDA_L; } //结束信号 void INA_IIC_Stop(void ) { IIC_SDA_L; IIC_SCL_H; INA_IIC_Delay(); IIC_SDA_H; INA_IIC_Delay(); IIC_SCL_L; IIC_SCL_H; IIC_SDA_H; } //读取应答信号 bool INA_IIC_ACK_Read(void) { bool ack; IIC_SDA_H; INA_IIC_SDA_IN(); IIC_SCL_H; INA_IIC_Delay(); if(IIC_SDA_READ() == SET) ack=false; else ack=true; IIC_SCL_L; INA_IIC_SDA_OUT(); return ack; } //发送应答信号 void INA_IIC_ACK_Send(bool ack) { IIC_SCL_L; if(ack == true) IIC_SDA_L; else IIC_SDA_H; IIC_SCL_H; INA_IIC_Delay(); IIC_SCL_L; } //IIC发送一位数据 void INA_IIC_Send_Byte(unsigned char byte) { unsigned char i; IIC_SCL_L; for(i=0;i<8;i++) { if(byte & 0x80 ) IIC_SDA_H; else IIC_SDA_L; IIC_SCL_H; INA_IIC_Delay(); IIC_SCL_L; INA_IIC_Delay(); byte<<=1; } INA_IIC_ACK_Read(); } //IIC读取一位数据 unsigned char INA_IIC_Read_Byte(void) { unsigned char i,byte=0; INA_IIC_SDA_IN(); for(i=0;i<8;i++) { IIC_SCL_H; byte<<=1; if(IIC_SDA_READ() == SET) byte |= 0x01; else byte &= 0xFE; IIC_SCL_L; INA_IIC_Delay(); } INA_IIC_SDA_OUT(); return byte; } #endif //读两位数据 void INA_Read_Byte_s(unsigned char reg,unsigned char *data) { INA_IIC_Start(); INA_IIC_Send_Byte(INA219_ADDRESS); //发送INA219地址s INA_IIC_Send_Byte(reg); INA_IIC_Start(); INA_IIC_Send_Byte(INA219_ADDRESS+0x01); //设置iic为读模式 *data=INA_IIC_Read_Byte(); data++; INA_IIC_ACK_Send(1); *data=INA_IIC_Read_Byte(); INA_IIC_ACK_Send(0); INA_IIC_Stop(); } //写寄存器 测试成功 void INA_REG_Write(unsigned char reg,unsigned int data) { unsigned char data_temp[2]; data_temp[0]=(unsigned char )(data>>8); data_temp[1]=(unsigned char )(data & 0xFF); INA_IIC_Start(); INA_IIC_Send_Byte(INA219_ADDRESS); //发送INA219地址 INA_IIC_Send_Byte(reg); //发送寄存器地址 INA_IIC_Send_Byte(data_temp[0]); //发送高8位数据 data++; INA_IIC_Send_Byte(data_temp[1]) ; //发送低8位数据 INA_IIC_Stop(); } //获取电压(单位:mv) unsigned int INA_GET_Voltage_MV(void) { unsigned char data_temp[2]; INA_Read_Byte_s(INA219_REG_BUSVOLTAGE,data_temp); return (int)((((data_temp[0]<<8)+data_temp[1]) >> 3)*4); //右移3为去掉:bit2,CNVR,OVF三位,再乘以 4MV (官方文档规定),得到当前总线的电压值 } //获取电流(单位:mA) short INA_GET_Current_MA(void) { unsigned char data_temp[2]; short temp; INA_Read_Byte_s(INA219_REG_CURRENT,data_temp); temp=(((data_temp[0]<<8)+data_temp[1])); if(temp<=0x7fff) { return (short)temp; } else { return (short) -temp; } //return (int)((((data_temp[0]<<8)+data_temp[1]))*IAN_I_LSB); //得到寄存器的值在乘以每位对应的值(IAN_I_LSB)得到实际的电流 // unsigned char data_temp[2]; // INA_REG_Write(INA219_REG_CONFIG,INA219_CONFIG_value); // INA_Read_Byte_s(INA219_REG_CURRENT,data_temp); // return (int)((((data_temp[0]<<8)+data_temp[1]))*IAN_I_LSB); //得到寄存器的值在乘以每位对应的值(IAN_I_LSB)得到实际的电流 } //获取当前功率(单位:mw) unsigned int INA_GET_Power_MW(void) { unsigned char data_temp[2]; INA_Read_Byte_s(INA219_REG_POWER,data_temp); return (int)(((data_temp[0]<<8)+data_temp[1])); //得到寄存器的值在乘以每位对应的值(INA_Power_LSB)得到实际的功率 } void INA_Init(void ) //初始化函数调用一次 { INA_IIC_INIT(); INA_REG_Write(INA219_REG_CONFIG,INA219_CONFIG_value); INA_REG_Write(INA219_REG_CALIBRATION,INA_CAL); }
TIMER.c
void Timer_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); TIM_InternalClockConfig(TIM3); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = 5000-1; TIM_TimeBaseInitStruct.TIM_Prescaler = 10000-1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct); TIM_ClearITPendingBit(TIM3,TIM_IT_Update); TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStruct); TIM_Cmd(TIM3,ENABLE); }
SERIAL.c
char Serial_RxPacket[100]; //定义接收数据包数组,数据包格式"@MSG\r\n" uint8_t Serial_RxFlag; //定义接收数据包标志位 /** * 函 数:串口初始化 * 参 数:无 * 返 回 值:无 */ void Serial_Init(void) { /*开启时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //开启USART2的时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //开启GPIOA的时钟 /*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed; GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA9引脚初始化为复用推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed; GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA10引脚初始化为上拉输入 GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA9复用为USART2 GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA10复用为USART2 /*USART初始化*/ USART_InitTypeDef USART_InitStructure; //定义结构体变量 USART_InitStructure.USART_BaudRate = 9600; //波特率 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制,不需要 USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //模式,发送模式和接收模式均选择 USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶校验,不需要 USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位,选择1位 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长,选择8位 USART_Init(USART2, &USART_InitStructure); //将结构体变量交给USART_Init,配置USART2 /*中断输出配置*/ USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接收数据的中断 /*NVIC中断分组*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2 /*NVIC配置*/ NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //选择配置NVIC的USART1线 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1 NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设 /*USART使能*/ USART_Cmd(USART2, ENABLE); //使能USART1,串口开始运行 } /** * 函 数:串口发送一个字节 * 参 数:Byte 要发送的一个字节 * 返 回 值:无 */ void Serial_SendByte(uint8_t Byte) { USART_SendData(USART2, Byte); //将字节数据写入数据寄存器,写入后USART自动生成时序波形 while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); //等待发送完成 /*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/ } /** * 函 数:串口发送一个数组 * 参 数:Array 要发送数组的首地址 * 参 数:Length 要发送数组的长度 * 返 回 值:无 */ void Serial_SendArray(uint8_t *Array, uint16_t Length) { uint16_t i; for (i = 0; i < Length; i ++) //遍历数组 { Serial_SendByte(Array[i]); //依次调用Serial_SendByte发送每个字节数据 } } /** * 函 数:串口发送一个字符串 * 参 数:String 要发送字符串的首地址 * 返 回 值:无 */ void Serial_SendString(char *String) { uint8_t i; for (i = 0; String[i] != '\0'; i ++)//遍历字符数组(字符串),遇到字符串结束标志位后停止 { Serial_SendByte(String[i]); //依次调用Serial_SendByte发送每个字节数据 } } /** * 函 数:次方函数(内部使用) * 返 回 值:返回值等于X的Y次方 */ uint32_t Serial_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; //设置结果初值为1 while (Y --) //执行Y次 { Result *= X; //将X累乘到结果 } return Result; } /** * 函 数:串口发送数字 * 参 数:Number 要发送的数字,范围:0~4294967295 * 参 数:Length 要发送数字的长度,范围:0~10 * 返 回 值:无 */ void Serial_SendNumber(uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i ++) //根据数字长度遍历数字的每一位 { Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); //依次调用Serial_SendByte发送每位数字 } } /** * 函 数:使用printf需要重定向的底层函数 * 参 数:保持原始格式即可,无需变动 * 返 回 值:保持原始格式即可,无需变动 */ int fputc(int ch, FILE *f) { Serial_SendByte(ch); //将printf的底层重定向到自己的发送字节函数 return ch; } /** * 函 数:自己封装的prinf函数 * 参 数:format 格式化字符串 * 参 数:... 可变的参数列表 * 返 回 值:无 */ void Serial_Printf(char *format, ...) { char String[100]; //定义字符数组 va_list arg; //定义可变参数列表数据类型的变量arg va_start(arg, format); //从format开始,接收参数列表到arg变量 vsprintf(String, format, arg); //使用vsprintf打印格式化字符串和参数列表到字符数组中 va_end(arg); //结束变量arg Serial_SendString(String); //串口发送字符数组(字符串) } /** * 函 数:USART2中断函数 * 参 数:无 * 返 回 值:无 * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行 * 函数名为预留的指定名称,可以从启动文件复制 * 请确保函数名正确,不能有任何差异,否则中断函数将不能进入 */ void USART2_IRQHandler(void) { static uint8_t RxState = 0; //定义表示当前状态机状态的静态变量 static uint8_t pRxPacket = 0; //定义表示当前接收数据位置的静态变量 if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) //判断是否是USART1的接收事件触发的中断 { uint8_t RxData = USART_ReceiveData(USART2); //读取数据寄存器,存放在接收的数据变量 /*使用状态机的思路,依次处理数据包的不同部分*/ /*当前状态为0,接收数据包包头*/ if (RxState == 0) { if (RxData == '@' && Serial_RxFlag == 0) //如果数据确实是包头,并且上一个数据包已处理完毕 { RxState = 1; //置下一个状态 pRxPacket = 0; //数据包的位置归零 } } /*当前状态为1,接收数据包数据,同时判断是否接收到了第一个包尾*/ else if (RxState == 1) { if (RxData == '\r') //如果收到第一个包尾 { RxState = 2; //置下一个状态 } else //接收到了正常的数据 { Serial_RxPacket[pRxPacket] = RxData; //将数据存入数据包数组的指定位置 pRxPacket ++; //数据包的位置自增 } } /*当前状态为2,接收数据包第二个包尾*/ else if (RxState == 2) { if (RxData == '\n') //如果收到第二个包尾 { RxState = 0; //状态归0 Serial_RxPacket[pRxPacket] = '\0'; //将收到的字符数据包添加一个字符串结束标志 Serial_RxFlag = 1; //接收数据包标志位置1,成功接收一个数据包 } } USART_ClearITPendingBit(USART2, USART_IT_RXNE); //清除标志位 } }
MYFLASH.c
/** * 函 数:FLASH读取一个32位的字 * 参 数:Address 要读取数据的字地址 * 返 回 值:指定地址下的数据 */ uint32_t MyFLASH_ReadWord(uint32_t Address) { return *((__IO uint32_t *)(Address)); //使用指针访问指定地址下的数据并返回 } /** * 函 数:FLASH读取一个16位的半字 * 参 数:Address 要读取数据的半字地址 * 返 回 值:指定地址下的数据 */ uint16_t MyFLASH_ReadHalfWord(uint32_t Address) { return *((__IO uint16_t *)(Address)); //使用指针访问指定地址下的数据并返回 } /** * 函 数:FLASH读取一个8位的字节 * 参 数:Address 要读取数据的字节地址 * 返 回 值:指定地址下的数据 */ uint8_t MyFLASH_ReadByte(uint32_t Address) { return *((__IO uint8_t *)(Address)); //使用指针访问指定地址下的数据并返回 } /** * 函 数:FLASH全擦除 * 参 数:无 * 返 回 值:无 * 说 明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在 */ void MyFLASH_EraseAllPages(void) { FLASH_Unlock(); //解锁 FLASH_EraseAllSectors(VoltageRange_3); //全擦除 FLASH_Lock(); //加锁 } /** * 函 数:FLASH扇擦除 * 参 数:PageAddress 要擦除扇的扇地址value between * FLASH_Sector_0 and FLASH_Sector_7. * 返 回 值:无 */ void MyFLASH_ErasePage(uint16_t PageAddress) { FLASH_Unlock(); //解锁 FLASH_EraseSector(PageAddress,VoltageRange_3); //页擦除 FLASH_Lock(); //加锁 } /** * 函 数:FLASH编程字 * 参 数:Address 要写入数据的字地址 * 参 数:Data 要写入的32位数据 * 返 回 值:无 */ void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data) { FLASH_Unlock(); //解锁 FLASH_ProgramWord(Address, Data); //编程字 FLASH_Lock(); //加锁 } /** * 函 数:FLASH编程半字 * 参 数:Address 要写入数据的半字地址 * 参 数:Data 要写入的16位数据 * 返 回 值:无 */ void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) { FLASH_Unlock(); //解锁 FLASH_ProgramHalfWord(Address, Data); //编程半字 FLASH_Lock(); //加锁 }
STORE.c
#define STORE_START_ADDRESS 0x08060000 //存储的起始地址 #define STORE_START_Sector FLASH_Sector_7 //存储的起始扇区 #define STORE_COUNT 512 //存储数据的个数 uint16_t Store_Data[STORE_COUNT]; //定义SRAM数组 /** * 函 数:参数存储模块初始化 * 参 数:无 * 返 回 值:无 */ void Store_Init(void) { /*判断是不是第一次使用*/ if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5) //读取第一个半字的标志位,if成立,则执行第一次使用的初始化 { MyFLASH_ErasePage(STORE_START_Sector); //擦除指定扇 MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5); //在第一个半字写入自己规定的标志位,用于判断是不是第一次使用 for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位 { MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000); //除了标志位的有效数据全部清0 } } /*上电时,将闪存数据加载回SRAM数组,实现SRAM数组的掉电不丢失*/ for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位 { Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2); //将闪存的数据加载回SRAM数组 } } /** * 函 数:参数存储模块保存数据到闪存 * 参 数:无 * 返 回 值:无 */ void Store_Save(void) { MyFLASH_ErasePage(STORE_START_Sector); //擦除指定扇 for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位 { MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, Store_Data[i]); //将SRAM数组的数据备份保存到闪存 } } /** * 函 数:参数存储模块将所有有效数据清0 * 参 数:无 * 返 回 值:无 */ void Store_Clear(void) { for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位 { Store_Data[i] = 0x0000; //SRAM数组有效数据清0 } Store_Save(); //保存数据到闪存 }
总结
通过近一个月的学习和使用,完成了基础任务和进阶任务,同时我还收获颇丰:
定时器应用:掌握了STM32定时器的精确配置与中断处理
I2C通信:熟练使用I2C总线驱动多个外设(OLED+INA219)
保护机制设计:理解了工业级保护电路的设计思路
人机交互:实现了串口命令行接口,提升系统可操作性
之前所做的开箱贴和过程贴