CH6-OLED

IIC-OLED

image-20240403002703456
OLED_POWER原理图

CubeMX

image-20240402233815111
下载线配置
image-20240402233501605
OLED引脚配置
image-20240402233712239
GPIO引脚配置
image-20240402233846175
RTC配置

image-20240402233941646

USART_DMA配置
image-20240402234031056
USART参数配置
image-20240402234101539
USART中断配置(IDLE)
image-20240402234205995
NVIC配置
image-20240402234357385
时钟树配置
image-20240402234506717
生成文件配置1
image-20240402234538464
生成文件配置2

MDK代码编写

oled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* IIC OLED */
void IIC_OLED_Init(unsigned char ms)//初始化函数,需要延时100ms
{
HAL_GPIO_WritePin(OLED_POWER_GPIO_Port, OLED_POWER_Pin, GPIO_PIN_RESET);//使能OLED,PB5=LOW
HAL_Delay(ms);//延时100ms
OLED_Init(); //OLED.C中自带的初始化函数
OLED_Clear();//OLED.C中自带的清屏函数,否则会出现乱码
}


void OLED_Write(unsigned char addr,unsigned char data)//OLED的写函数
{
unsigned char pdata[2];//发送的存储数组
pdata[0]=addr;//存储第一个数据
pdata[1]=data;//存储第二个数据


HAL_I2C_Master_Transmit(&hi2c3,0x78,pdata,2,0xff);//在阻塞模式下将大量数据写入特定的内存地址,第一个参数为I2C指针,即用I2C1 还是 I2C2;第二个参数器件地址uint16_t DevAddress(0X78);第三个参数指向发送数据的指针;第四个参数数据的长度;第五个参数发送所需要的时间

}

function.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "function.h"
#include "gpio.h"
#include "stdio.h" //fputc() 函数
#include "string.h"
#include "oled.h"

extern UART_HandleTypeDef huart2; //外部调用串口的结构体
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;//外部调用串口DMA的结构体

extern I2C_HandleTypeDef hi2c3;//IIC的结构体
extern RTC_HandleTypeDef hrtc;//RTC结构体

#define Usart_RX_buffer_len 100//允许不定长接收的数据的缓存区长度
unsigned char usart_rx_sec_len;//接收到一帧串口数据的长度
unsigned char usart_rx_sec_flag;//接收到一帧串口数据接收时的标志位
unsigned char usart_rx_buffer[Usart_RX_buffer_len];//接收数据缓存数组

/********************************* 需要放进function.h *******************************************/
/* IDLE接收函数组 */
void Usart_RX_Init(void)
{
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);//使能IDLE的接收中断
HAL_UART_Receive_DMA(&huart2,usart_rx_buffer,Usart_RX_buffer_len);//打开DMA串口接收函数,第一个变量为串口2结构体,第二个变量为接收的存储数组,第三个为接收数据的大小
}

void Usart_RX_EXTI(void)//需要将`USART_RX_IDLE_EXTI()`放进stm32l0xx_it.c中的`void USART2_IRQHandler(void)`中
{
if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) == SET)//判断IDLE的接收是否产生中断,如果接收到一帧数据,那么就会触发中断,FLAG被置1
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中断标志位
HAL_UART_DMAStop(&huart2);//关闭DMA防止在处理数据时候接收数据,产生干扰

usart_rx_sec_len = Usart_RX_buffer_len - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//计算出接收缓存中的数据长度
usart_rx_sec_flag=1;//将检测接收完成的标志位置1
}
}
void Usart_RX_DEAL(void)
{
if(usart_rx_sec_flag==1)//判断接收完成标志位是否置1
{

if((Usart_RX_mess[0]=='L') && (Usart_RX_mess[1]=='E') && (Usart_RX_mess[2]=='D'))//用户自定义的函数,在这里我们可以根据需要,设置我们输入特定指令所触发的功能
{
HAL_UART_Transmit_DMA(&huart2,Usart_RX_mess,Usart_RX_sec_len);//
}


usart_rx_sec_flag=0;//将接收完成标志位置0
usart_rx_sec_len=0;//将接收到的数据清零
HAL_UART_Receive_DMA(&huart2,usart_rx_buffer,Usart_RX_buffer_len);//重新设置DMA下次要接收的数据字节数,使能DMA进入接收数据状态
}
}

/* IIC OLED */
void IIC_OLED_Init(unsigned char ms)//初始化函数,需要延时100ms
{
HAL_GPIO_WritePin(OLED_POWER_GPIO_Port, OLED_POWER_Pin, GPIO_PIN_RESET);//使能OLED,PB5=LOW
HAL_Delay(ms);//延时100ms
OLED_Init(); //OLED.C中自带的初始化函数
OLED_Clear();//OLED.C中自带的清屏函数,否则会出现乱码
}


void OLED_Write(unsigned char addr,unsigned char data)//OLED的写函数
{
unsigned char pdata[2];//发送的存储数组
pdata[0]=addr;//存储第一个数据
pdata[1]=data;//存储第二个数据

HAL_I2C_Master_Transmit(&hi2c3,0x78,pdata,2,0xff);//在阻塞模式下将大量数据写入特定的内存地址,第一个参数为I2C指针,即用I2C1 还是 I2C2;第二个参数器件地址uint16_t DevAddress(0X78);第三个参数指向发送数据的指针;第四个参数数据的长度;第五个参数发送所需要的时间
}

/* RTC */
unsigned char * RTC_Data(void)
{
static unsigned char rtc_data[7];

RTC_TimeTypeDef rtc_time_data;
RTC_DateTypeDef rtc_date_data;

HAL_RTC_GetTime(&hrtc,&rtc_time_data,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&rtc_date_data,RTC_FORMAT_BIN);

rtc_data[0]=rtc_date_data.Year;
rtc_data[1]=rtc_date_data.Month;
rtc_data[2]=rtc_date_data.WeekDay;
rtc_data[3]=rtc_date_data.Date;

rtc_data[4]=rtc_time_data.Hours;
rtc_data[5]=rtc_time_data.Minutes;
rtc_data[6]=rtc_time_data.Seconds;

return rtc_data;
}
/********************************* 不用放进function.h *******************************************/
/* printf函数的子函数 */
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,0xffff);
//while(__HAL_UART_GET_IT(&huart2,UART_IT_TC) == RESET){}

return ch;
}

/* 外部中断函数 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(USER_KEY_Pin==GPIO_Pin)
{
flag_send_rtc=1;
}
}

function.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef __FUNCTION_H__
#define __FUNCTION_H__


void Usart_RX_Init(void);
void Usart_RX_EXTI(void);
void Usart_RX_DEAL(void);

void IIC_OLED_Init(unsigned char ms);
void OLED_Write(unsigned char addr,unsigned char data);

unsigned char * RTC_Data(void);

#endif

main.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "function.h"
#include "stdio.h"
#include "oled.h"
int main(void)
{
Usart_RX_Init();
IIC_OLED_Init(100);
unsigned char IIC_oled_data_1[16];
unsigned char IIC_oled_data_2[16];
unsigned char *RTC_data;
extern unsigned char flag_send_rtc;
while(1)
{
RTC_data=RTC_Data();
sprintf((char *)IIC_oled_data_2,"%d:%d:%d",RTC_data[4],RTC_data[5],RTC_data[6]);
sprintf((char *)IIC_oled_data_1,"LQB");
OLED_ShowString(0,IIC_oled_data_1);
OLED_ShowString(2,IIC_oled_data_2);
if(flag_send_rtc)
{
flag_send_rtc=0;
printf("RTC:%d-%d-%d %d:%d:%d \r\n",2000+RTC_data[0],RTC_data[1],RTC_data[3],RTC_data[4],RTC_data[5],RTC_data[6]);
}
Usart_RX_DEAL();
}
}

==1.第15届包含的IIC数据包中oled.h中需要添加上#incldue “main.h”==

==2.需要将USART_RX_IDLE_EXTI()放进stm32l0xx_it.c中的void USART2_IRQHandler(void)中==

==3.中断一定是UART_FLAG_IDLE==

==4.编译需要选择USE MicroLIB==

image-20240403002004859