智能家居模拟系统的实现

// 智能家居模拟系统-文档
// 2015.12.14 by Huangtao

目前由以下组成:
由 STM32F103系列单片机 + RT-Thread嵌入式实时操作系统 +
串口转WIFI模块 + LED + LCD + L298 + 风扇 + 温度传感器

自定义通信协议:
1、'L' + 控制LED字符(0x11,0x10,0x21...)
2、'F' + 风扇控制符(0xf0,0xf1,0xf2...)
3、'TT',返回温度

手机APP端可以控制LED开关,获取温度,调节风扇转速。

/*
application.c
2015.12.4 by Huangtao
 
 */

#include <board.h>
#include <rtthread.h>

#ifdef  RT_USING_COMPONENTS_INIT
#include <components.h>
#endif  /* RT_USING_COMPONENTS_INIT */

#ifdef RT_USING_DFS
/* dfs filesystem:ELM filesystem init */
#include <dfs_elm.h>
/* dfs Filesystem APIs */
#include <dfs_fs.h>
#endif

#ifdef RT_USING_RTGUI
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>
#include <rtgui/calibration.h>
#endif

// 我加入的
#include "led.h"
#include "LCD5110.h"
#include "ds18b20.h"
#include "usart.h"
#include "TIM3_PWM.h"

// Thread ID
static rt_thread_t led_id = RT_NULL;
static rt_thread_t fan_id = RT_NULL;
static rt_thread_t lcd5110_id = RT_NULL;
static rt_thread_t ds18b20_id = RT_NULL;
static rt_thread_t uart2_id = RT_NULL;

#define CPU_USAGE_CALC_TICK    10
#define CPU_USAGE_LOOP        100

static rt_uint8_t  cpu_usage_major = 0;
//static cpu_usage_minor= 0;
static rt_uint32_t total_count = 0;

/*
自定义通信协议:
ledControl:
'L'+
    0x10----led1 off
    0x11----led1 on
    0x20----led2 off
    0x21----led2 on
    ...
fanControl:
'F'+
    0xf0----fan off
    0xf1----speed 1
    0xf2----speed 2
    ...

*/
static short temperature = 0;
static char ledControl = 0;
static char fanControl = 0;
// 访问温度的互斥量
static rt_mutex_t mutexTemperature = RT_NULL;
static rt_mutex_t mutexLed = RT_NULL;
static rt_mutex_t mutexFan = RT_NULL;

// stm32_usart2发送缓冲区
static char uart_tx_buffer[64] = "\nOpen uart2 OK.\0";
// stm32_usart2接收缓冲区
static char uart_rx_buffer[64];
// USART 接收消息结构
struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};
// 用于接收消息的消息队列控制块
static rt_mq_t rx_mq;
static struct rt_messagequeue  my_rx_mq;
// 消息队列中用到的放置消息的内存池
static char msg_pool[1024];


static void cpu_usage_idle_hook()
{
    rt_tick_t tick;
    rt_uint32_t count;
    volatile rt_uint32_t loop;

    if (total_count == 0)
    {
        /* get total count */
        rt_enter_critical();
        tick = rt_tick_get();
        while(rt_tick_get() - tick < CPU_USAGE_CALC_TICK)
        {
            total_count ++;
            loop = 0;
            while (loop < CPU_USAGE_LOOP) loop ++;
        }
        rt_exit_critical();
    }

    count = 0;
    /* get CPU usage */
    tick = rt_tick_get();
    while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK)
    {
        count ++;
        loop  = 0;
        while (loop < CPU_USAGE_LOOP) loop ++;
    }

    /* calculate major and minor */
    if (count < total_count)
    {
        count = total_count - count;
        cpu_usage_major = (count * 100) / total_count;
        //cpu_usage_minor = ((count * 100) % total_count) * 100 / total_count;
    }
    else
    {
        total_count = count;

        /* no CPU usage */
        cpu_usage_major = 0;
        //cpu_usage_minor = 0;
    }

}

void cpu_usage_init()
{
    /* set idle thread hook */
    rt_thread_idle_sethook(cpu_usage_idle_hook);
}


/*
// led
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t led_stack[ 512 ];
static struct rt_thread led_thread;*/
static void led_thread_entry(void* parameter)
{
    rt_hw_led_init();

    while (1)
    {
        rt_mutex_take(mutexLed, RT_WAITING_FOREVER);
        if(ledControl == 0x11)
        {
            // led1 on 
            rt_hw_led_on(0);
        }
        else if(ledControl == 0x10)
        {
            // led1 off 
            rt_hw_led_off(0);
        }
        else if(ledControl == 0x21)
        {
            // led2 on 
            rt_hw_led_on(1);
        }
        else if(ledControl == 0x20)
        {
            // led2 off 
            rt_hw_led_off(1);
        }
        rt_mutex_release(mutexLed);
        
        // 顺便清屏
        //ClearScreen();
        rt_thread_delay( 10 );  

    }

}

static void fan_thread_entry(void* parameter)
{
    short Compare2Num = 0;
    TIM3_PWM_Init(900,5);    // PWM频率=72000/5/900

    while(1)
    {
        rt_mutex_take(mutexFan, RT_WAITING_FOREVER);
        switch(fanControl)
        {
            case 0xf0:  Compare2Num=0;    break;    //
            case 0xf1:  Compare2Num=100;  break;    // 1档
            case 0xf2:  Compare2Num=150;  break;    // 2档
            case 0xf3:  Compare2Num=200;  break;    // ...
            case 0xf4:  Compare2Num=250;  break;
            case 0xf5:  Compare2Num=300;  break;
            case 0xf6:  Compare2Num=350;  break;
            case 0xf7:  Compare2Num=400;  break;
            case 0xf8:  Compare2Num=450;  break;
            case 0xf9:  Compare2Num=500;  break;
            case 0xfa:  Compare2Num=600;  break;
            case 0xfb:  Compare2Num=700;  break;
            case 0xfc:  Compare2Num=800;  break;
            case 0xfd:  Compare2Num=900;  break;    // 13档

            default:  break;
        }
        rt_mutex_release(mutexFan);

        TIM_SetCompare2(TIM3, Compare2Num);

        rt_thread_delay(10);
    }
}

// lcd5110
static void lcd5110_thread_entry(void* parameter)
{
    LcdInit();

    while(1)
    {
        DispString(15,0,"RT-Thread");
        DispString(0,1,"CPU:");
        DispNum(30,1,cpu_usage_major);
        DispChar(45,1,'%');

        rt_thread_delay( 5 );

    }

}

// ds18b20
static void ds18b20_thread_entry(void* parameter)
{
    short showTemp;
    //rt_err_t result;
    while(DS18B20_Init());

    while(1)
    {
        DispString(0,3,"Temp: ");

        rt_mutex_take(mutexTemperature, RT_WAITING_FOREVER);
        temperature = DS18B20_Get_Temp();
        showTemp = temperature;
        rt_mutex_release(mutexTemperature);

        if(showTemp<0)
        {
            DispChar(40,3,'-');         
            showTemp=-showTemp;   
        }
        else 
            DispChar(40,3,' '); 

        DispNum(48,3,((u16)showTemp)/10);    //显示正数部分    
        DispChar(60,3,'.');     
        DispNum(67,3,((u16)showTemp)%10);    //显示小数部分 

        rt_thread_delay( 5 );
    }

}

// uart2
//===============================================
// 数据到达回调函数
//  rt_err_t(*)(rt_device_t dev, rt_size_t size) 
rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    struct rx_msg msg;
    msg.dev = dev;
    msg.size = size;
    if(size >=2)
    {
        // 发送消息到消息队列中
        rt_mq_send(rx_mq, &msg, sizeof(struct rx_msg));
    }
    return RT_EOK;
}

static void uart2_thread_entry(void* parameter)
{
    rt_err_t result = RT_EOK;
    struct rx_msg msg;
    rt_device_t stm32_uart2;
    rt_uint32_t rx_length;

    // 根据注册名查找设备
    stm32_uart2 = rt_device_find("uart2");
    if (stm32_uart2 != RT_NULL)
    {
        // 初始化设备
        rt_device_init(stm32_uart2);
        // 设置回调函数(当设备接收到数据执行)
        rt_device_set_rx_indicate(stm32_uart2, uart_input);
        // 打开设备
        rt_device_open(stm32_uart2, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);
    }

    rt_device_write(stm32_uart2, 0, &uart_tx_buffer[0], 18);
    
    while(1)
    {
        // 从消息队列中读取消息, RT_WAITING_FOREVER
        result = rt_mq_recv(rx_mq, &msg, sizeof(struct rx_msg), RT_WAITING_FOREVER);
        // 成功收到消息
        if(result == RT_EOK)
        {
            rx_length = (sizeof(uart_rx_buffer) - 1) > msg.size ?
                        msg.size : sizeof(uart_rx_buffer) - 1;

            // 读取消息
            rx_length = rt_device_read(msg.dev, 0, &uart_rx_buffer[0], rx_length);
            uart_rx_buffer[rx_length] = '\0';

            
            // 'F' + fanControl
            if(uart_rx_buffer[0] == 0x46)
            {
                rt_mutex_take(mutexFan, RT_WAITING_FOREVER);
                fanControl = uart_rx_buffer[1];  
                rt_mutex_release(mutexFan);
            }
            // 'L' + ledControl
            else if(uart_rx_buffer[0] == 0x4c)
            {
                rt_mutex_take(mutexLed, RT_WAITING_FOREVER);
                ledControl = uart_rx_buffer[1];
                rt_mutex_release(mutexLed);
            }
            
            // 收到'T',则发送温度
            else if(uart_rx_buffer[0] == 0x54)
            {
                rt_mutex_take(mutexTemperature, RT_WAITING_FOREVER);
                uart_tx_buffer[0] = temperature & 0xff;
                uart_tx_buffer[1] = (temperature >> 8) & 0xff;
                uart_tx_buffer[2] = '\0';
                rt_mutex_release(mutexTemperature);

                rt_device_write(stm32_uart2, 0, &uart_tx_buffer[0], 2);
            }
    
            // 回显观察
            //rt_device_write(stm32_uart2, 0, &uart_rx_buffer[0], rx_length);

        }

        //rt_thread_delay( 5 );
    }

}


void rt_init_thread_entry(void* parameter)
{
#ifdef RT_USING_COMPONENTS_INIT
    /* initialization RT-Thread Components */
    rt_components_init();
#endif

#ifdef  RT_USING_FINSH
    finsh_set_device(RT_CONSOLE_DEVICE_NAME);
#endif  /* RT_USING_FINSH */

    /* Filesystem Initialization */
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)
    /* mount sd card fat partition 1 as root directory */
    if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
    {
        rt_kprintf("File System initialized!\n");
    }
    else
        rt_kprintf("File System initialzation failed!\n");
#endif  /* RT_USING_DFS */

#ifdef RT_USING_RTGUI
    {
        extern void rt_hw_lcd_init();
        extern void rtgui_touch_hw_init(void);

        rt_device_t lcd;

        /* init lcd */
        rt_hw_lcd_init();

        /* init touch panel */
        rtgui_touch_hw_init();

        /* find lcd device */
        lcd = rt_device_find("lcd");

        /* set lcd device as rtgui graphic driver */
        rtgui_graphic_set_device(lcd);

#ifndef RT_USING_COMPONENTS_INIT
        /* init rtgui system server */
        rtgui_system_server_init();
#endif

        calibration_set_restore(cali_setup);
        calibration_set_after(cali_store);
        calibration_init();
    }
#endif /* #ifdef RT_USING_RTGUI */
}

// 创建线程和初始化
//============================================================
int rt_application_init(void)
{
    rt_thread_t init_thread;

    // 初始化消息队列
    rt_mq_init(&my_rx_mq, "mqt", &msg_pool[0], sizeof(struct rx_msg), sizeof(msg_pool), RT_IPC_FLAG_FIFO);
    rx_mq = &my_rx_mq;

    // 创建互斥锁
    mutexTemperature = rt_mutex_create("mutexTemperature", RT_IPC_FLAG_FIFO);
    if (mutexTemperature == RT_NULL)
    {
        return 0;
    }
    mutexLed = rt_mutex_create("mutexLed", RT_IPC_FLAG_FIFO);
    if (mutexLed == RT_NULL)
    {
        return 0;
    }
    mutexFan = rt_mutex_create("mutexFan", RT_IPC_FLAG_FIFO);
    if (mutexFan == RT_NULL)
    {
        return 0;
    }

    /*rt_err_t result;
    // 静态创建 led 线程 
    result = rt_thread_init(&led_thread,                // 线程控制块内存地址
                            "led",                      // 线程名称
                            led_thread_entry,           // 线程入口入口函数
                            RT_NULL,                    // 线程入口入口函数参数
                            (rt_uint8_t*)&led_stack[0], // 线程栈起始地址
                            sizeof(led_stack),          // 线程栈大小
                            20,                         // 线程优先级
                            5);                         // 线程时间片大小
    if (result == RT_EOK)
    {
        rt_thread_startup(&led_thread);
    }*/
    

    // 动态创建 led 线程
    led_id = rt_thread_create("led",            // 线程名称
                            led_thread_entry,   // 线程入口入口函数 
                            RT_NULL,            // 线程入口入口函数参数 
                            512,                // 线程栈大小
                            21,                 // 线程优先级
                            10);                // 线程时间片大小
    // 如果获得线程控制块,启动这个线程
    if (led_id != RT_NULL) 
        rt_thread_startup(led_id);

     // 动态创建 fan 线程
    fan_id = rt_thread_create("fan",            // 线程名称
                            fan_thread_entry,   // 线程入口入口函数 
                            RT_NULL,            // 线程入口入口函数参数 
                            1024,                // 线程栈大小
                            20,                 // 线程优先级
                            10);                // 线程时间片大小
    // 如果获得线程控制块,启动这个线程
    if (fan_id != RT_NULL) 
        rt_thread_startup(fan_id);
    
    // 动态创建 lcd5110 线程
    lcd5110_id = rt_thread_create("lcd5110",        // 线程名称
                            lcd5110_thread_entry,   // 线程入口入口函数 
                            RT_NULL,                // 线程入口入口函数参数 
                            512,                   // 线程栈大小
                            20,                     // 线程优先级
                            20);                    // 线程时间片大小
    if (lcd5110_id != RT_NULL) 
        rt_thread_startup(lcd5110_id);

    // 动态创建 ds18b20 线程
    ds18b20_id = rt_thread_create("ds18b20",        // 线程名称
                            ds18b20_thread_entry,   // 线程入口入口函数 
                            RT_NULL,                // 线程入口入口函数参数 
                            1024,                   // 线程栈大小
                            19,                     // 线程优先级
                            20);                    // 线程时间片大小
    if (ds18b20_id != RT_NULL) 
        rt_thread_startup(ds18b20_id);

    // 动态创建 usart2 线程
    uart2_id = rt_thread_create("uart2",            // 线程名称
                            uart2_thread_entry,     // 线程入口入口函数 
                            RT_NULL,                // 线程入口入口函数参数 
                            2048,                   // 线程栈大小
                            19,                     // 线程优先级
                            15);                    // 线程时间片大小
    if (uart2_id != RT_NULL) 
        rt_thread_startup(uart2_id);


    // CPU %
    cpu_usage_init();


#if (RT_THREAD_PRIORITY_MAX == 32)
    init_thread = rt_thread_create("init",
                                   rt_init_thread_entry, RT_NULL,
                                   2048, 8, 20);
#else
    init_thread = rt_thread_create("init",
                                   rt_init_thread_entry, RT_NULL,
                                   2048, 80, 20);
#endif

    if (init_thread != RT_NULL)
        rt_thread_startup(init_thread);

    return 0;
}

 

posted @ 2015-12-15 19:44  ht-beyond  阅读(1490)  评论(0编辑  收藏  举报