您的位置:首页 > 其它

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

2017-09-08 11:45 411 查看
龙芯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;
}


运行结果(串口打印)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息