鸿蒙硬件HI3861-OLED扫雷版本
使用HI3861实现在OLED1602上面实现扫雷
效果请看:https://www.bilibili.com/video/BV1U54y1r78j/
1.OLED&按键
首先第一步是需要移植I2C显示屏代码
移植请看:https://bbs.elecfans.com/jishu_1999539_1_1.html
按键使用到的是OLED上面的两个按键,一个控制左一个控制右,HI3861上的按键时选中
2.扫雷代码
在OLED初始化启动之后调用mineclear_Start函数
static_library("mineclear") {
sources = [
"mineclear.c"
]
include_dirs = [
"//domains/iot/link/mineclear",
"//kernel/liteos_m/components/cmsis/2.0",
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
"//domains/iot/link/ssd1306",
]
}
mineclear.h
#ifndef MINECLEAR_H
#define MINECLEAR_H
#define MINECLEAR_WIDTH 8
#define MINECLEAR_HEIGHT 16
#define MINECLEAR_MAX 128
#define MINE_MAX 10
#define ADC_LENGTH 64
#define VLT_MIN 100
void mineclear_Start(void);
void mine_init(void);
void mineMake(void);
#endif
mineclear.c
#include "mineclear.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ohos_init.h"
#include "ssd1306.h"
#include <stddef.h>
#include "cmsis_os2.h"
#include <time.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include <hi_stdlib.h>
#include "hi_adc.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include <hi_stdlib.h>
const uint32_t W = 8, H = 8;
uint8_t fonts[][8] = {
{0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00}, // 默认状态
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 没有雷
{0x00,0x42,0x24,0x18,0x18,0x24,0x42,0x00}, // 有雷
{0x55,0x80,0x01,0x80,0x01,0x80,0x01,0xAA}, // 选中
};
uint32_t mine_data2[MINECLEAR_MAX];
uint32_t mineClear_data2[MINECLEAR_MAX];
hi_u16 key_adc_buf[ADC_LENGTH] = { 0 };
int key_flg;
uint32_t key_status = 0;
static uint32_t play_index = 0;
hi_void convert_to_voltage2(hi_u32 data_len){
hi_u32 i;
float vlt_max = 0;
float vlt_min = VLT_MIN;
float vlt_val = 0;
hi_u16 vlt;
for (i = 0; i < data_len; i++) {
vlt = key_adc_buf[i];
float voltage = (float)vlt * 1.8 * 4 / 4096.0; /* vlt * 1.8 * 4 / 4096.0: Convert code into voltage */
vlt_max = (voltage > vlt_max) ? voltage : vlt_max;
vlt_min = (voltage < vlt_min) ? voltage : vlt_min;
}
vlt_val = (vlt_min + vlt_max)/2.0;
if((vlt_val > 0.4) && (vlt_val < 0.6)){
key_status = 1;
//printf("[key]K1\r\n");
}
if((vlt_val > 0.8) && (vlt_val < 1.1)){
key_status = 2;
//printf("[key]K2\r\n",vlt_val);
}
if((vlt_val > 0.01) && (vlt_val < 0.3)){
key_status = 3;
//printf("[key]K3\r\n",vlt_val);
}
}
void starttest2(void){
hi_u32 ret, i;
hi_u16 data; /* 10 */
memset_s(key_adc_buf, sizeof(key_adc_buf), 0x0, sizeof(key_adc_buf));
for (i = 0; i < ADC_LENGTH; i++) {
ret = hi_adc_read((hi_adc_channel_index)HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_1, HI_ADC_CUR_BAIS_DEFAULT, 0);
if (ret != HI_ERR_SUCCESS) {
printf("ADC Read Fail\n");
return;
}
key_adc_buf[i] = data;
}
convert_to_voltage2(ADC_LENGTH);
}
void ssd1306_Draw(uint32_t x, uint32_t y,int type){
ssd1306_DrawRegion(x, y, W, H, fonts[type], sizeof(fonts[type]), W);
}
void mineClear_Refresh2(uint32_t d[]){
uint32_t i = 0, j = 0, h = 0;
ssd1306_Fill(Black);
for(i=0;i<MINECLEAR_WIDTH;i++){
for(j=0;j<MINECLEAR_HEIGHT;j++){
uint32_t md_data = d[h];
if(md_data == 0){
ssd1306_Draw((j*W),(i*H),0);
}else if(md_data == 1){
ssd1306_Draw((j*W),(i*H),2);
}else if(md_data == 102){
ssd1306_Draw((j*W),(i*H),3);
}else if(md_data == 2){
ssd1306_Draw((j*W),(i*H),1);
}else{
}
h++;
}
}
ssd1306_UpdateScreen();
}
void mine_init(void){
uint32_t i;
ssd1306_Fill(Black);
for(i=0;i<MINECLEAR_MAX;i++){
mineClear_data2[i] = 0;
}
mineClear_Refresh2(mineClear_data2);
}
/**
* 制作炸弹
*/
void mineMake(void){
int count = MINE_MAX-1;
int mine_rand = 0;
while (true){
if(count<0) break;
mine_rand = rand() % MINECLEAR_MAX;
if (mine_data2[mine_rand] == 0){
mine_data2[mine_rand] = 1;
count--;
}
}
//mineClear_Refresh2(mine_data2);
}
/**
* 移动光标
*/
void mouse_move(void){
int index = play_index - 1;
printf("[key]2--%d\r\n",index);
if(index == 0){
if(mineClear_data2[1] == 102 && mineClear_data2[1] != 0){
mineClear_data2[1] = 0;
}
if(mineClear_data2[MINECLEAR_MAX-1] == 102 && mineClear_data2[MINECLEAR_MAX-1] != 0){
mineClear_data2[MINECLEAR_MAX-1] = 0;
}
}else if(index == (MINECLEAR_MAX-1)){
printf("[key]laster\r\n");
if(mineClear_data2[0] == 102 && mineClear_data2[0] != 0){
mineClear_data2[0] = 0;
}
if(mineClear_data2[index-1] == 102 && mineClear_data2[index-1] != 0){
mineClear_data2[index-1] = 0;
}
}else{
if(mineClear_data2[index-1] == 102 && mineClear_data2[index-1] != 0){
mineClear_data2[index-1] = 0;
}
if(mineClear_data2[index+1] == 102 && mineClear_data2[index+1] != 0){
mineClear_data2[index+1] = 0;
}
}
if(mineClear_data2[index] != 2){
mineClear_data2[index] = 102;
}
mineClear_Refresh2(mineClear_data2);
ssd1306_UpdateScreen();
}
void mine_find_num(void){
mineClear_data2[play_index-1] = 2;
ssd1306_UpdateScreen();
// 获取周围8方块的雷
}
static void *MineClearTask(const char *arg){
(void)arg;
play_index = 1;
while(1){
starttest2();
if(key_status == 1){ // 左移动
if(play_index == 0){
play_index = MINECLEAR_MAX;
}
play_index--;
mouse_move();
}
if(key_status == 2){ // 右移动
if(play_index > (MINECLEAR_MAX-1)){
play_index = 0;
}
play_index++;
mouse_move();
}
if(key_status == 3){ // 选中
if(mine_data2[play_index-1] == 1){ // 炸弹
mineClear_data2[play_index-1] = 1;
mineClear_Refresh2(mineClear_data2);
osDelay(40);
mineClear_Refresh2(mine_data2);
break;
}else{
mine_find_num();
}
//printf("[11]%d\r\n",play_index);
}
key_status = 0;
osDelay(10);
}
printf("GAME OVER\r\n");
return NULL;
}
void mineclear_Start(void){
osThreadAttr_t attr;
attr.name = "MineClearTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = 34;
mineMake();
// osDelay(10);
mine_init();
osDelay(10);
if (osThreadNew((osThreadFunc_t)MineClearTask, NULL, &attr) == NULL) {
printf("[DoorDemo] Falied to create DoorTask!\n");
}
}