本例程是一个简单的串口通信的交互例程,通过了RT-thread系统来实现。
简要叙述程序思路:
- 创建两个进程句柄,serial与serial2。
- 调用一系列初始化串口设备的函数,分别是rt_device_find(查找设备),rt_device_set_rx_indicate(设置接收回调函数)。
- 启动线程,调用函数并检测接受到的信息
- 接收到对应信息后调用函数向JQ8900模块发送命令
- 同时保留了按钮操控的效果,通过rt_pin_attach_irq设置按钮中断函数
以下给出源码:
/* 基于RTT的手机通过esp8266操作JQ8900功放模块的一种方式 所用开发板 野火指南者 WiFi模块 ESP8266 功放模块 JQ8900 RTT版本 4.0.2(野火BSP) */ #include <rtthread.h> #include <rtdevice.h> #include <board.h> #ifndef KEY0_PIN_NUM #define KEY0_PIN_NUM GET_PIN(A, 0) /* PA0 Key1 pin脚*/ #endif #ifndef KEY1_PIN_NUM #define KEY1_PIN_NUM GET_PIN(C, 13) /* PC13 Key2 pin脚*/ #endif #ifndef SAMPLE_UART_NAME #define SAMPLE_UART_NAME "uart2" /* JQ8900所接串口 请先事先在env中打开*/ #endif #ifndef UART_NAME #define UART_NAME "uart3" /* ESP8266所接串口*/ #endif static rt_device_t serial; static rt_device_t serial2; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 句柄默认设置 */ static struct rt_semaphore rx_sem; static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { rt_sem_release(&rx_sem); return RT_EOK; } static void Re_music(void *args) { static char buffer1[4]={0xAA,0x05,0x00,0xAF}; //JQ8900上一曲命令 rt_uint32_t tx_length; tx_length=4; int i = 0; while(i < 4){ rt_device_write(serial,0,&buffer1[i],tx_length); //循环发送 i++;} rt_kprintf("jun\n"); } static void next_music(void *args) { static char buffer1[4]={0xAA,0x06,0x00,0xB0}; //JQ8900下一曲命令 rt_uint32_t tx_length; tx_length=4; int i = 0; while(i < 4){ rt_device_write(serial,0,&buffer1[i],tx_length); i++;} rt_kprintf("bian\n"); } static void nmsl(void *parameter){ char ch; while (1) { while (rt_device_read(serial2, -1, &ch, 1) != 1) { rt_sem_take(&rx_sem, RT_WAITING_FOREVER); } if(ch == 'a'){ //esp8266检测接受信息,为a则调用函数 Re_music(0); } if(ch == 'b'){ next_music(0); } } } static void serial_thread_entry(void *parameter) { // char ch; while (1) { rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP); rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, Re_music, RT_NULL); //设置按钮中断回调函数 rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE); rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP); rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, next_music, RT_NULL); rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE); } } static int mdr5(int argc, char *argv[]) { rt_err_t ret = RT_EOK; char uart_name[RT_NAME_MAX]; if (argc == 2) { rt_strncpy(uart_name, argv[1], RT_NAME_MAX); } else { rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX); } serial = rt_device_find(uart_name); serial2 = rt_device_find(UART_NAME); if (!serial) { rt_kprintf("find %s failed!\n", uart_name); return RT_ERROR; } if (!serial2) { rt_kprintf("find %s failed!\n", UART_NAME); return RT_ERROR; } rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); config.baud_rate = BAUD_RATE_9600; //串口设置为9600 config.data_bits = DATA_BITS_8; config.stop_bits = STOP_BITS_1; config.parity = PARITY_NONE; rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); rt_device_set_rx_indicate(serial, uart_input); rt_device_open(serial2, RT_DEVICE_FLAG_INT_RX); rt_device_set_rx_indicate(serial2, uart_input); rt_thread_t thread1 = rt_thread_create("serial2", nmsl, RT_NULL, 1024, 25, 10); if (thread1 != RT_NULL) { rt_thread_startup(thread1); } else { ret = RT_ERROR; } rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10); if (thread != RT_NULL) { rt_thread_startup(thread); } else { ret = RT_ERROR; } return ret; } MSH_CMD_EXPORT(mdr5, uart JUN);
值得注意的是,JQ8900模块的波特率是9600,需要使用rt_device_control函数来设置串口波特率,而esp8266则不用
本程序还设置了一个接受信号量,用来在串口接收到信息之后发送信号量,来表示已经接受到数据。