目录
oled.c
?模拟iic起始信号
?模拟iic停止信号
?模拟iic读取从机应答信号
iic读取一个字节byte?
?iic写命令
iic写数据?
对oled写入一个字节?
?设置起始页地址
开显示
关显示?
清屏幕?
?显示字符
oled_init 是固定的
?显示字符串
计算m^n次方?编辑?
?显示数字
显示汉字?
oled.h?
Dht11.c?
在函数调用中
DHT11_Start开始信号
接收信号
dht11.h?
?任务函数1
任务函数2
oled.c
我们要用高阻态,所以用开漏输出
?模拟iic起始信号
?模拟iic停止信号
?模拟iic读取从机应答信号
iic读取一个字节byte?
高位先行
?iic写命令
iic写数据?
对oled写入一个字节?
?设置起始页地址
把x,y想象成在第四象限
一个数和1与得到它本身 ,高四位固定了为0001
?
开显示
?
关显示?
清屏幕?
?显示字符
一页一页写的
但是有的字符占两页 16 * 8,两页
8 * 6 ,一页显示一个字符
每个字符 16 个字节
一个字符占两页,所以上面是写入上半页,下面是写入下半夜
八个点阵一个字节
8 * 2 = 16个字节
比方说O是47行,O的偏移量为47,则O之前有47*16个字节 c是O的偏移量 i<8
c*16+i就是前8个字节也就是第一页
c*16+i+8就是后8个字节也就是第二页
oled_init 是固定的
?显示字符串
计算m^n次方?
?显示数字
789 i
789/100%10 = 7 10^(3-1)
789/10%10 = 8 10^(2-1)
789/1%10 = 9 10^(1-1)
显示汉字?
no :第几个字
每个字占两行
先讲下数组a[2][3] 两行三列
a[0]a[0] a[0]a[1] a[0][2]
a[1]a[0] a[1]a[1] a[1][2]
比如 “技” 这个字是第0个 2*0还是0也就是第1行(第一页) 2*0 + 1 = 1也就是第2行(第2页)
比如 “新” 这个字是第1个 2*1=2 也就是第三行(第三页) 2*1 + 1 = 3也就是第4行(第4页)
?
oled.h?
?
Dht11.c?
配置两个GPIO,为什么会有两个GPIO呢? 因为dht11是通过stm32主机先输出(主机先发送起始信号等待dht11响应之后io口才开始接收数据) 所以第一个输出,浮空输出,既可以输出高也可以输出低
第二个是输入模式,选择下拉输入
void DHT11_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void DHT11_GPIO_Init1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
在函数调用中
第一个是gpio初始化,输出模式
第二个是开始信号
第三个是接收信号
void DHT11_UpdateData()
{
DHT11_GPIO_Init();
DHT11_Start();
DHT11_ReceptionBuff();
}
DHT11_Start开始信号
void DHT11_Start(void)
{
data0;
delay_ms(20);
data1;
delay_us(10);
DHT11_GPIO_Init1(); //切换到接收模式
while(DHT11_Back()); //等待响应信号
}
接收信号
接收5个字节,每个字节8位
接收数字0是 26us~28us
接收数字1是 70us
我们折中选择40us,方便区分数字0还是数字1
我们用两个while
第一个while(read_data) 接收低电平
第二个while(!read_data)接收高电平
并且把初始位(i)设置为0位
__nop();函数时空语句,他不会因为我们进去while里面后就不能执行下面的语句了
每读取一位 就向左移一位 移到低位
每次移位后中间间隔50us,这里延迟30us
while(read_data);接收下一位时,中间是有一个低电平的,并且每个低电平是50us
所以我们这里每次进去都要等待低电平,进行下一次for循环
把i的值放到Rxbuff里
void DHT11_ReceptionBuff()
{
uint8_t y=1;
uint16_t i;
uint8_t x;
for(x=0;x<5;x++)
{
i=0;
for(y=1;y<9;y++)
{
while(read_data)
{
__nop();
}
delay_us(40);
while(!read_data)
{
__nop();
}
i= i<<1;
delay_us(30);
if(read_data)
{
i |=1;
}
while(read_data);
}
Rxbuff[x] =i;
}
}
?
?
dht11.h?
#ifndef _DHT11_H
#define _DHT11_H
#include "stm32f10x.h"
#define data1 GPIO_SetBits(GPIOB, GPIO_Pin_11)
#define data0 GPIO_ResetBits(GPIOB, GPIO_Pin_11)
#define read_data GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)
void DHT11_GPIO_Init(void);
void DHT11_GPIO_Init1(void);
void DHT11_Start(void);
void DHT11_ReceptionBuff();
void DHT11_UpdateData();
extern uint16_t Rxbuff[5];
#endif
?任务函数1
void list_task(void *pvParameters)
{
delay_ms(1500);
OLED_Init(); //OLED3?ê??ˉ
OLED_Clear();
OLED_ShowCHinese(0,2,6); //μ±
OLED_ShowCHinese(16,2,7); //?°
OLED_ShowCHinese(32,2,8); //??
OLED_ShowCHinese(48,2,9); //?è
OLED_ShowCHinese(66,2,10); //£o
OLED_ShowCHinese(90,2,15); //.
OLED_ShowCHinese(112,2,11); //C
OLED_ShowCHinese(16,5,6); //μ±
OLED_ShowCHinese(32,5,7); //?°
OLED_ShowCHinese(48,5,12); //êa
OLED_ShowCHinese(64,5,9); //?è
OLED_ShowCHinese(80,5,10); //£o
OLED_ShowCHinese(112,5,13); //.
while(1)
{
uint16_t i;
uint8_t k;
uint8_t kk;
uint8_t kkk;
DHT11_UpdateData();
i = Rxbuff[0]+ Rxbuff[1]+Rxbuff[2]+ Rxbuff[3];
if(Rxbuff[4] ==i)
{
k=Rxbuff[2];
kk=Rxbuff[0];
kkk=Rxbuff[3];
OLED_ShowNum(74,2,k/10,3,3);
OLED_ShowNum(82,2,k%10,3,3);
OLED_ShowNum(98,2,kkk,3,3);
OLED_ShowNum(88,5,kk/10,3,3);
OLED_ShowNum(98,55,kkk%10,3,3);
}
delay_ms(2000);
}
}
任务函数2
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
|