在RT-Thread上使用龙芯1c库中的硬件I2C接口

龙芯1c库的Git是  http://git.oschina.NET/caogos/OpenLoongsonLib1c
RT-Thread的git是  https://github.com/RT-Thread/rt-thread
龙芯1c库是为龙芯1c单片机封装的常用外设接口集合,类似于STM32库。不仅可以用于裸机编程,还可以和实时系统(比如RT-Thread等)配合使用。这里就是将龙芯1c库和RT-Thread配合使用,其中龙芯1c库中硬件I2C相关接口已经移植到RT-Thread,并且合并到RT-Thread官方git中。
其实,在RT-Thread下使用龙芯1c库中的函数与在裸机编程下是一样的,都是先包含头文件,然后直接调用。
本文以温湿度传感器AM2320为例、将AM2320接在龙芯1c的I2C0(或I2C1、I2C2)上,通过RT-Thread中龙芯1c库的硬件I2C接口来读取温湿度信息,以此演示如何在RT-Thread下如何龙芯1c库中的硬件I2C接口。关于龙芯1C库中硬件I2C相关接口的详细描述请移步到 【龙芯1c库】封装硬件I2C接口和使用示例

源码清单

只需要在RT-Thread下新建一个线程,然后在该线程的入口函数中调用硬件I2C接口读取温湿度信息即可,具体源码如下

bsp\ls1cdev\applications\application.c

/*
 * File      : application.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006-2012, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date                Author         Notes
 * 2010-06-25          Bernard        first version
 * 2011-08-08          lgnq           modified for Loongson LS1B
 * 2015-07-06          chinesebear    modified for Loongson LS1C
 */

#include <rtthread.h>
#include <components.h>
#include "net/synopGMAC.h"
#include <lwip/api.h>
#include "rthw.h"
#include "ls1c.h"
#include "ls1c_public.h"
#include "ls1c_i2c.h"
#include "ls1c_pin.h"


// 测试用的线程  
#define THREAD_TEST_PRIORITY                    (25)  
#define THREAD_TEST_STACK_SIZE                  (4*1024)        // 4k  
#define THREAD_TEST_TIMESLICE                   (10)  


// am2320返回的数据长度
#define AM2320_RSP_DATA_SIZE            (8)

// I2C1,引脚CAMDATA4(GPIO54)和CAMDATA5(GPIO55)的第四复用
#define LS1C_I2C_SDA1_GPIO54            (54)
#define LS1C_I2C_SCL1_GPIO55            (55)

// I2C2,引脚CAMDATA6(GPIO56)和CAMDATA7(GPIO57)的第四复用
#define LS1C_I2C_SDA2_GPIO56            (56)
#define LS1C_I2C_SCL2_GPIO57            (57)


// 读取的消息中每字节的含义
enum
{
    AM2320_RSP_FUNC_ID = 0,             // 功能码
    AM2320_RSP_LEN,                     // 数据长度
    AM2320_RSP_HUMI_HIGH,               // 湿度高位
    AM2320_RSP_HUMI_LOW,                // 湿度低位
    AM2320_RSP_TEMP_HIGH,               // 温度高位
    AM2320_RSP_TEMP_LOW,                // 温度低位
    AM2320_RSP_CRC_LOW,                 // CRC低位
    AM2320_RSP_CRC_HIGH,                // CRC高位
};

  
struct rt_thread thread_test;  
ALIGN(8) rt_uint8_t thread_test_stack[THREAD_TEST_STACK_SIZE];  


/*
 * 计算crc
 * @ptr 待计算crc的数据的首地址
 * @len 数据长度
 */
unsigned short am2320_crc16(unsigned char *ptr, unsigned char len)
{
    unsigned short crc = 0xFFFF;
    unsigned char i;

    while (len--)
    {
        crc ^= *ptr++;
        for (i=0; i<8; i++)
        {
            if (crc & 0x01)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }

    return crc;
}


// 测试用的线程的入口  
void thread_test_entry(void *parameter)  
{
    ls1c_i2c_info_t i2c_info;
    int slave_addr = 0xb8 >> 1;     // AM2320手册中的地址0xB8是8位的,而我们这里地址是指其前7位
    unsigned char send_buff[] = {0x03, 0x00, 0x04};
    unsigned char recv_buff[AM2320_RSP_DATA_SIZE] = {0};
    unsigned short recved_crc, calced_crc;
    int temp, humi;
    
    // I2C2,引脚CAMDATA6(GPIO56)和CAMDATA7(GPIO57)的第四复用
    pin_set_remap(LS1C_I2C_SDA2_GPIO56, PIN_REMAP_FOURTH);
    pin_set_remap(LS1C_I2C_SCL2_GPIO57, PIN_REMAP_FOURTH);
    i2c_info.clock = 50*1000;       // 50kb/s
    i2c_info.I2Cx = LS1C_I2C_2;
    i2c_init(&i2c_info);
    
/*
    // 使用I2C1,引脚CAMDATA4(GPIO54)和CAMDATA5(GPIO55)的第四复用
    pin_set_remap(LS1C_I2C_SDA1_GPIO54, PIN_REMAP_FOURTH);
    pin_set_remap(LS1C_I2C_SCL1_GPIO55, PIN_REMAP_FOURTH);
    i2c_info.clock = 50*1000;       // 50kb/s
    i2c_info.I2Cx = LS1C_I2C_1;
    i2c_init(&i2c_info);
*/

/*
    // 使用I2C0,不需要复用
    i2c_info.clock = 50*1000;       // 50kb/s
    i2c_info.I2Cx = LS1C_I2C_0;
    i2c_init(&i2c_info);
*/
    
    while (1)  
    {
        // 唤醒传感器
        i2c_send_start_and_addr(&i2c_info, slave_addr, LS1C_I2C_DIRECTION_WRITE);
        i2c_receive_ack(&i2c_info);
        rt_thread_delay(1);
        i2c_send_stop(&i2c_info);

        // 发送读指令
        i2c_send_start_and_addr(&i2c_info, slave_addr, LS1C_I2C_DIRECTION_WRITE);
        i2c_receive_ack(&i2c_info);
        i2c_send_data(&i2c_info, send_buff, sizeof(send_buff));
        i2c_send_stop(&i2c_info);

        // 读取温湿度信息
        rt_thread_delay(2);
        i2c_send_start_and_addr(&i2c_info, slave_addr, LS1C_I2C_DIRECTION_READ);
        i2c_receive_ack(&i2c_info);
        i2c_receive_data(&i2c_info, recv_buff, AM2320_RSP_DATA_SIZE);
        i2c_send_stop(&i2c_info);

        // 校验crc
        recved_crc = (recv_buff[AM2320_RSP_CRC_HIGH] << 8) + recv_buff[AM2320_RSP_CRC_LOW];
        calced_crc = am2320_crc16(recv_buff, 6);
        if (recved_crc != calced_crc)
        {
            rt_kprintf("[%s] crc error! recved_crc=0x%x, calced_crc=0x%x\n", 
                        __FUNCTION__, recved_crc, calced_crc);
        }

        // 计算温度湿度
        humi = (recv_buff[AM2320_RSP_HUMI_HIGH] * 0xff + recv_buff[AM2320_RSP_HUMI_LOW]) / 10;
        temp = (recv_buff[AM2320_RSP_TEMP_HIGH] * 0xff + recv_buff[AM2320_RSP_TEMP_LOW]) / 10;
        rt_kprintf("[%s] temp=%d, humi=%d\n", __FUNCTION__, temp, humi);
        
        // 间隔3s,再采集
        rt_thread_delay(3 * RT_TICK_PER_SECOND);  
    }  
}  



void rt_init_thread_entry(void *parameter)
{
	/* initialization RT-Thread Components */
	rt_components_init();

    // 网口EMAC初始化
	rt_hw_eth_init();
}

int rt_application_init(void)
{
	rt_thread_t tid;
    rt_err_t result;

	/* create initialization thread */
	tid = rt_thread_create("init",
							rt_init_thread_entry, RT_NULL,
							4096, RT_THREAD_PRIORITY_MAX/3, 20);
	if (tid != RT_NULL)
		rt_thread_startup(tid);

  
    // 初始化测试用的线程  
    result = rt_thread_init(&thread_test,   
                            "thread_test",  
                            thread_test_entry,  
                            RT_NULL,  
                            &thread_test_stack[0],  
                            sizeof(thread_test_stack),  
                            THREAD_TEST_PRIORITY,  
                            THREAD_TEST_TIMESLICE);  
    if (RT_EOK == result)  
    {  
        rt_thread_startup(&thread_test);  
    }  
    else  
    {  
        return -1;  
    }  

	return 0;
}

运行结果(串口打印)



猜你喜欢

转载自blog.csdn.net/caogos/article/details/77892951