init
This commit is contained in:
380
Source/EC800M_4G.c
Normal file
380
Source/EC800M_4G.c
Normal file
@@ -0,0 +1,380 @@
|
||||
#include "EC800M_GPS.h"
|
||||
#include "EC800M_4G.h"
|
||||
|
||||
int _r = 0;
|
||||
int _timeout = 1;
|
||||
|
||||
// 存放4G数据
|
||||
char _4G_DATA[_4G_DATA_LENGTH];
|
||||
int _4G_DATA_LEN;
|
||||
|
||||
// 重置4G数据缓冲区
|
||||
void _4g_reset_data()
|
||||
{
|
||||
memset(_4G_DATA, 0, _4G_DATA_LENGTH);
|
||||
_4G_DATA_LEN = 0;
|
||||
}
|
||||
|
||||
void uart_send_string(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
uart_write_blocking(EC800M_4G_UART, (const uint8_t *)str, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int _4G_uart_read_string(char *_4G_DATA, int *_4G_DATA_LEN)
|
||||
{
|
||||
int _time = 0;
|
||||
int timeout = 3000; // 设置超时时间为3秒,单位为毫秒
|
||||
|
||||
while (1) {
|
||||
// 检查是否超时
|
||||
if (_time >= timeout) {
|
||||
printf("EC800M _4G_uart_read_string() 读取超时\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uart_is_readable(EC800M_4G_UART)) {
|
||||
if (*_4G_DATA_LEN < _4G_DATA_LENGTH - 1) {
|
||||
char c = uart_getc(EC800M_4G_UART);
|
||||
_4G_DATA[(*_4G_DATA_LEN)++] = c;
|
||||
_4G_DATA[*_4G_DATA_LEN] = '\0';
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep_ms(1); // 稍微延迟一下,等待下一个循环
|
||||
_time++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _4G_uart_read_string_until_response(char *DATA, int *DATA_LEN, const char *expected_response)
|
||||
{
|
||||
|
||||
int timeout = 10000; // 设置超时时间为10秒,单位为毫秒
|
||||
|
||||
*DATA_LEN = 0;
|
||||
int _time = 0;
|
||||
while (1) {
|
||||
while (uart_is_readable(EC800M_4G_UART)) {
|
||||
if (*DATA_LEN < _4G_DATA_LENGTH) {
|
||||
char c = uart_getc(EC800M_4G_UART);
|
||||
DATA[(*DATA_LEN)++] = c;
|
||||
DATA[*DATA_LEN] = '\0'; // 添加字符串结束符
|
||||
}
|
||||
|
||||
if (strstr(DATA, expected_response) != NULL) {
|
||||
return 0; // 找到了预期的响应,退出循环
|
||||
} else {
|
||||
//printf("%s\n", DATA);
|
||||
}
|
||||
}
|
||||
_time++;
|
||||
sleep_ms(1); // 等待一小段时间再继续读取
|
||||
|
||||
if (_time >= timeout) {
|
||||
_time = 0;
|
||||
printf("EC800M _4G_uart_read_string_until_response() 读取超时\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int EC800M_4G_INIT()
|
||||
{
|
||||
// AT+CFUN=1,1
|
||||
//uart_send_string("AT+CFUN=1,1\r\n");
|
||||
|
||||
// AT+CGREG=2
|
||||
uart_send_string("AT+CGREG=2\r\n");
|
||||
sleep_ms(10);
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QIACT? Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+CGATT=1
|
||||
uart_send_string("AT+CGATT=1\r\n");
|
||||
sleep_ms(10);
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+CGATT=1 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+CEREG=2
|
||||
uart_send_string("AT+CEREG=2\r\n");
|
||||
sleep_ms(10);
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+CEREG=2 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+QICSGP=1
|
||||
uart_send_string("AT+QICSGP=1\r\n");
|
||||
//sleep_ms(10);
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QICSGP=1 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+QIACT=1
|
||||
uart_send_string("AT+QIACT=1\r\n");
|
||||
sleep_ms(10);
|
||||
if (-1 == _4G_uart_read_string(_4G_DATA, &_4G_DATA_LEN)) {
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+QIACT?
|
||||
uart_send_string("AT+QIACT?\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QIACT? Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+QIDEACT=1
|
||||
uart_send_string("AT+QIDEACT=1\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QIDEACT=1 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
// AT+QIOPEN=1,0,"TCP","47.240.75.93",8009,0,1
|
||||
uart_send_string("AT+QIOPEN=1,0,\"TCP\",\"123.60.29.178\",8009,0,1\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(_4G_DATA, &_4G_DATA_LEN, "0,0")) {
|
||||
printf("EC800M Module 4G \"AT+QIOPEN=1,0,\"TCP\",\"123.60.29.178\",8009,0,1\r\n\" Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
|
||||
/*
|
||||
// AT+QISTATE=1,0
|
||||
uart_send_string("AT+QISTATE=1,0\r\n");
|
||||
if (-1 == _4G_uart_read_string(_4G_DATA, &_4G_DATA_LEN)) {
|
||||
printf("EC800M Module 4G AT+QISTATE=1,0 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", _4G_DATA, _4G_DATA_LEN);
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int receive_data(char *input_string)
|
||||
{
|
||||
char temp_buffer[270] = { 0 };
|
||||
char received_data[270] = { 0 };
|
||||
int received_data_length = 0;
|
||||
int step = 1;
|
||||
char *token = NULL;
|
||||
char *start = NULL;
|
||||
char *end = NULL;
|
||||
size_t temp_length = 0;
|
||||
|
||||
// 在指针不为NULL时才进行后续操作
|
||||
start = strstr(input_string, "QIURC");
|
||||
if (start == NULL) {
|
||||
printf("Error: 'QIURC' not found\n");
|
||||
return -1; // 返回错误代码
|
||||
}
|
||||
|
||||
end = strstr(start, "\r\n");
|
||||
if (end == NULL) {
|
||||
printf("Error: '\\r\\n' not found\n");
|
||||
return -1; // 返回错误代码
|
||||
}
|
||||
|
||||
temp_length = end - start; // 计算子字符串的长度
|
||||
if (temp_length >= sizeof(temp_buffer)) {
|
||||
printf("Error: Substring length exceeds buffer size\n");
|
||||
return -1; // 返回错误代码
|
||||
}
|
||||
// 复制子字符串到 TEMP 中
|
||||
memcpy(temp_buffer, start, temp_length);
|
||||
temp_buffer[temp_length] = '\0'; // 添加字符串结束标志
|
||||
|
||||
// 使用 strtok 解析 TEMP 字符串
|
||||
token = strtok(temp_buffer, ",");
|
||||
while (token != NULL) {
|
||||
if (step == 3) {
|
||||
received_data_length = atoi(token);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
step++;
|
||||
}
|
||||
|
||||
// 检查 received_data_length 是否为有效值
|
||||
if (received_data_length <= 0 || received_data_length >= (int)sizeof(received_data)) {
|
||||
printf("Error: Invalid received_data_length value\n");
|
||||
return -1; // 返回错误代码
|
||||
}
|
||||
// 复制数据到 received_data 中
|
||||
memcpy(received_data, end + 2, received_data_length);
|
||||
received_data[received_data_length] = '\0'; // 添加字符串结束标志
|
||||
|
||||
printf("%s", received_data);
|
||||
|
||||
return 0; // 返回成功代码
|
||||
}
|
||||
|
||||
// 查询Socket状态
|
||||
int CHECK_TCP_STATUS()
|
||||
{
|
||||
char RECV[270] = { 0 };
|
||||
int RECV_LEN = 0;
|
||||
int step = 1;
|
||||
int socket_state = 0;
|
||||
|
||||
printf("Query Socket status!!!\n");
|
||||
|
||||
uart_send_string("AT+QISTATE=1,0\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(RECV, &RECV_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QISTATE=1,0 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", RECV, RECV_LEN);
|
||||
|
||||
char *token = strtok(RECV, ",");
|
||||
while (token != NULL) {
|
||||
if (step == 7) {
|
||||
socket_state = atoi(token);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
step++;
|
||||
}
|
||||
|
||||
printf("socket_state: %d\n", socket_state);
|
||||
|
||||
return socket_state;
|
||||
}
|
||||
|
||||
// 重新连接TCP
|
||||
int TCP_RESTART()
|
||||
{
|
||||
char RECV[270] = { 0 };
|
||||
int RECV_LEN = 0;
|
||||
|
||||
printf("Re-establish TCP!!!\n");
|
||||
|
||||
uart_send_string("AT+QICLOSE=0\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(RECV, &RECV_LEN, "OK")) {
|
||||
printf("EC800M Module 4G AT+QICLOSE=0 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", RECV, RECV_LEN);
|
||||
|
||||
uart_send_string("AT+QIOPEN=1,0,\"TCP\",\"123.60.29.178\",8009,0,1\r\n");
|
||||
if (-1 == _4G_uart_read_string_until_response(RECV, &RECV_LEN, "0,0")) {
|
||||
printf("EC800M Module 4G AT+QICLOSE=0 Timeout!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s %d\n", RECV, RECV_LEN);
|
||||
|
||||
sleep_ms(3000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <stdbool.h>
|
||||
// 全局变量,表示TCP连接是否已经成功建立过
|
||||
bool tcp_connection_established = false;
|
||||
|
||||
int establish_tcp_connection()
|
||||
{
|
||||
// 如果TCP连接已经成功建立过,则直接返回成功
|
||||
if (tcp_connection_established) {
|
||||
printf("TCP connection already established.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _r = EC800M_4G_INIT(); // 第一次建立TCP
|
||||
int retry_count = 0; // 重试计数器
|
||||
|
||||
while (_r == -1 && retry_count < TCP_MAX_RETRY) {
|
||||
printf("TCP establishment failed! Retrying...\n");
|
||||
_r = EC800M_4G_INIT(); // 重新建立TCP连接
|
||||
retry_count++;
|
||||
sleep_ms(9000); // 等待一段时间后重试
|
||||
}
|
||||
|
||||
if (_r == -1) {
|
||||
printf("Failed to establish TCP connection after %d retries.\n", TCP_MAX_RETRY);
|
||||
return -1; // 返回连接失败
|
||||
} else {
|
||||
printf("TCP connection established successfully.\n");
|
||||
// 标记TCP连接已经成功建立过
|
||||
tcp_connection_established = true;
|
||||
return 0; // 返回连接成功
|
||||
}
|
||||
}
|
||||
|
||||
int EC800M_4G_RECV(char *string)
|
||||
{
|
||||
char RECV[1024] = { 0 };
|
||||
int RECV_LEN = 0;
|
||||
uint8_t CTRLZ[1];
|
||||
|
||||
uart_send_string("AT+QISEND=0\r\n");
|
||||
sleep_ms(100);
|
||||
uart_send_string(string);
|
||||
|
||||
CTRLZ[0] = 0X1A;
|
||||
uart_write_blocking(EC800M_4G_UART, CTRLZ, 1);
|
||||
|
||||
if (-1 == _4G_uart_read_string_until_response(RECV, &RECV_LEN, "SEND OK")) {
|
||||
printf("EC800M Module 4G AT+QISEND=0 Timeout!\n");
|
||||
_timeout++;
|
||||
if (2 != CHECK_TCP_STATUS()) {
|
||||
if (-1 == TCP_RESTART()) {
|
||||
printf("TCP RESTART ERROR!\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
receive_data(RECV);
|
||||
|
||||
if (2 != CHECK_TCP_STATUS()) {
|
||||
if (-1 == TCP_RESTART()) {
|
||||
printf("TCP RESTART ERROR!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sleep_ms(3000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EC800M_4G(void *p)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
EC800M_UART_INIT();
|
||||
|
||||
while (1) {
|
||||
printf("EC800M Module 4G\n");
|
||||
|
||||
int result = establish_tcp_connection();
|
||||
if (result == 0) {
|
||||
;
|
||||
}
|
||||
EC800M_4G_RECV("abcd\r\n");
|
||||
EC800M_4G_RECV("aixiao.me\r\n");
|
||||
|
||||
|
||||
|
||||
EC800M_GPS(NULL);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
40
Source/EC800M_4G.h
Normal file
40
Source/EC800M_4G.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef EC800M_4G_H
|
||||
#define EC800M_4G_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/uart.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
|
||||
#define EC800M_4G_UART uart1
|
||||
#define EC800M_4G_UART_TX 9 // 接EC800M TX 上
|
||||
#define EC800M_4G_UART_RX 8 // 接EC800M RX 上
|
||||
#define EC800M_4G_DATA_BITS 8
|
||||
#define EC800M_4G_STOP_BITS 1
|
||||
#define EC800M_4G_UART_BAUD_RATE 115200
|
||||
|
||||
#define TCP_MAX_RETRY 3 // TCP建立最大重试次数
|
||||
#define _4G_DATA_LENGTH 8192
|
||||
|
||||
extern void EC800M_4G(void *p);
|
||||
|
||||
#endif
|
||||
253
Source/EC800M_GPS.c
Normal file
253
Source/EC800M_GPS.c
Normal file
@@ -0,0 +1,253 @@
|
||||
#include "EC800M_GPS.h"
|
||||
|
||||
// 存放GPS数据
|
||||
char GPSDATA[GPSDATA_LENGTH];
|
||||
int GPSDATA_LEN;
|
||||
|
||||
// 重置GPS数据缓冲区
|
||||
void gps_reset_data()
|
||||
{
|
||||
memset(GPSDATA, 0, GPSDATA_LENGTH);
|
||||
GPSDATA_LEN = 0;
|
||||
}
|
||||
|
||||
// 初始化 EC800M 串口
|
||||
int EC800M_UART_INIT()
|
||||
{
|
||||
uart_init(EC800M_GPS_UART, GPS_UART_BAUD_RATE);
|
||||
gpio_set_function(GPS_UART_TX, GPIO_FUNC_UART);
|
||||
gpio_set_function(GPS_UART_RX, GPIO_FUNC_UART);
|
||||
uart_set_hw_flow(EC800M_GPS_UART, false, false);
|
||||
uart_set_format(EC800M_GPS_UART, GPS_DATA_BITS, GPS_STOP_BITS, UART_PARITY_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _gps_uart_send_string(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
uart_write_blocking(EC800M_GPS_UART, (const uint8_t *)str, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int _gps_uart_read_string()
|
||||
{
|
||||
int _time = 0;
|
||||
int timeout = 3000; // 设置超时时间为7秒,单位为毫秒
|
||||
|
||||
while (1) {
|
||||
if (uart_is_readable(EC800M_GPS_UART)) {
|
||||
char c = uart_getc(EC800M_GPS_UART);
|
||||
|
||||
if (GPSDATA_LEN < GPSDATA_LENGTH - 1) {
|
||||
GPSDATA[GPSDATA_LEN++] = c;
|
||||
GPSDATA[GPSDATA_LEN] = '\0';
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查是否超时
|
||||
if (_time >= timeout) {
|
||||
printf("EC800M _gps_uart_read_string() 读取超时\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sleep_ms(1); // 稍微延迟一下,等待下一个循环
|
||||
_time++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gps_uart_read_string_until_response(const char *expected_response)
|
||||
{
|
||||
gps_reset_data();
|
||||
|
||||
int timeout = 3000; // 设置超时时间为7秒,单位为毫秒
|
||||
|
||||
int i = 0;
|
||||
int _time = 0;
|
||||
while (1) {
|
||||
while (uart_is_readable(EC800M_GPS_UART)) {
|
||||
char c = uart_getc(EC800M_GPS_UART);
|
||||
GPSDATA[i++] = c;
|
||||
GPSDATA[i] = '\0'; // 添加字符串结束符
|
||||
|
||||
if (strstr(GPSDATA, expected_response) != NULL) {
|
||||
GPSDATA_LEN = i;
|
||||
return 0; // 找到了预期的响应,退出循环
|
||||
}
|
||||
}
|
||||
_time++;
|
||||
sleep_ms(1); // 等待一小段时间再继续读取
|
||||
|
||||
if (_time >= timeout) {
|
||||
_time = 0;
|
||||
printf("EC800M _gps_uart_read_string_until_response() 读取超时\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GPS 经纬度转10进制
|
||||
long double convertToDecimal(long double coordinate)
|
||||
{
|
||||
int degree = (int)(coordinate / 100);
|
||||
long double minutes = coordinate - degree * 100;
|
||||
return degree + minutes / 60;
|
||||
}
|
||||
|
||||
// 解释GPS数据
|
||||
int EC800M_GPS_DATA_PARSING(char *GPS_DATA, GPS_ * gps_)
|
||||
{
|
||||
int i = 1;
|
||||
char *p;
|
||||
char *p1;
|
||||
char *token;
|
||||
|
||||
p = strchr(GPS_DATA, ':');
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p1 = strstr(p + 2, "\r\n");
|
||||
if (p1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char GPS_DATA_[p1 - p];
|
||||
memset(gps_->time, 0, 20);
|
||||
memset(gps_->N, 0, 20);
|
||||
memset(gps_->E, 0, 20);
|
||||
memset(GPS_DATA_, 0, p1 - p);
|
||||
memcpy(GPS_DATA_, p + 2, p1 - p - 2 + 1);
|
||||
GPS_DATA_[p1 - p - 2 + 1] = '\0';
|
||||
printf("%s\n", GPS_DATA_);
|
||||
|
||||
token = strtok(GPS_DATA_, ",");
|
||||
while (token != NULL) {
|
||||
if (i == 1) {
|
||||
strcpy(gps_->time, token);
|
||||
}
|
||||
if (i == 2) {
|
||||
strcpy(gps_->N, token);
|
||||
}
|
||||
if (i == 3) {
|
||||
strcpy(gps_->E, token);
|
||||
}
|
||||
|
||||
token = strtok(NULL, ",");
|
||||
i++;
|
||||
}
|
||||
|
||||
gps_->N[strlen(gps_->N) - 1] = '\0';
|
||||
gps_->E[strlen(gps_->E) - 1] = '\0';
|
||||
|
||||
// 095921.00
|
||||
char hours[3] = { 0 };
|
||||
char minutes[3] = { 0 };
|
||||
char seconds[9] = { 0 };
|
||||
char *p2 = gps_->time;
|
||||
memcpy(hours, p2, 2);
|
||||
memcpy(minutes, p2 + 2, 2);
|
||||
memcpy(seconds, p2 + 4, 2);
|
||||
//printf("GPS 修正时间: %d:%s:%s\n", atoi(hours) + 8, minutes, seconds);
|
||||
|
||||
sprintf(gps_->time, "%d:%s:%s", atoi(hours) + 8, minutes, seconds);
|
||||
sprintf(gps_->N, "%.6lf", convertToDecimal(atof(gps_->N)));
|
||||
sprintf(gps_->E, "%.6lf", convertToDecimal(atof(gps_->E)));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 初始化 EC800M GPS
|
||||
int EC800M_GPS_INIT()
|
||||
{
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"outport\",\"uartdebug\"\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"nmeasrc\",1\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"gpsnmeatype\",63\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"gnssconfig\",1\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"autogps\",0\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSCFG=\"apflash\",0\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPS=1\r\n");
|
||||
sleep_ms(100);
|
||||
if (-1 == _gps_uart_read_string()) {
|
||||
return -1;
|
||||
}
|
||||
// 打印第一次初始化输出
|
||||
//printf("%s %d\n", GPSDATA, strlen(GPSDATA));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EC800M_GPS(void *p)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
|
||||
//while (1) {
|
||||
printf("EC800M Module GPS\n");
|
||||
|
||||
GPS_ gps_;
|
||||
memset(gps_.time, 0, 20);
|
||||
memset(gps_.N, 0, 20);
|
||||
memset(gps_.E, 0, 20);
|
||||
|
||||
if (-1 == EC800M_GPS_INIT()) {
|
||||
printf("EC800M_INIT() 第一次初始化失败\n");
|
||||
}
|
||||
|
||||
_gps_uart_send_string("AT+QGPSLOC=0\r\n");
|
||||
if (-1 == _gps_uart_read_string_until_response("OK")) {
|
||||
printf("重启EC800M模块 GPS\n");
|
||||
EC800M_GPS_INIT();
|
||||
}
|
||||
sleep_ms(300);
|
||||
//printf("%s %d %d\n", GPSDATA, strlen(GPSDATA), GPSDATA_LEN);
|
||||
|
||||
if (NULL == strstr(GPSDATA, "ERROR") && GPSDATA_LEN > 0) {
|
||||
EC800M_GPS_DATA_PARSING(GPSDATA, &gps_);
|
||||
printf(" T: %s\n N: %s\n E: %s\n", gps_.time, gps_.N, gps_.E);
|
||||
printf(" NE: %s, %s\n", gps_.N, gps_.E);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
//}
|
||||
|
||||
return;
|
||||
}
|
||||
41
Source/EC800M_GPS.h
Normal file
41
Source/EC800M_GPS.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef EC800M_GPS_H
|
||||
#define EC800M_GPS_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
|
||||
#define EC800M_GPS_UART uart1
|
||||
#define GPS_UART_TX 9 // 接EC800M TX 上
|
||||
#define GPS_UART_RX 8 // 接EC800M RX 上
|
||||
#define GPS_DATA_BITS 8
|
||||
#define GPS_STOP_BITS 1
|
||||
#define GPS_UART_BAUD_RATE 115200
|
||||
|
||||
#define GPSDATA_LENGTH 8192
|
||||
|
||||
typedef struct GPS_ {
|
||||
char time[20];
|
||||
char N[20];
|
||||
char E[20];
|
||||
} GPS_;
|
||||
|
||||
extern int EC800M_UART_INIT();
|
||||
extern void EC800M_GPS(void *p);
|
||||
|
||||
#endif
|
||||
137
Source/FreeRTOSConfig.h
Normal file
137
Source/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* FreeRTOS V202212.00
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler Related */
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_TICKLESS_IDLE 0
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 1
|
||||
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
||||
#define configMAX_PRIORITIES 32
|
||||
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
|
||||
/* Synchronization Related */
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
#define configUSE_QUEUE_SETS 1
|
||||
#define configUSE_TIME_SLICING 1
|
||||
#define configUSE_NEWLIB_REENTRANT 0
|
||||
#define configENABLE_BACKWARD_COMPATIBILITY 0
|
||||
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
|
||||
|
||||
/* System */
|
||||
#define configSTACK_DEPTH_TYPE uint32_t
|
||||
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
|
||||
|
||||
/* Memory allocation related definitions. */
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#define configTOTAL_HEAP_SIZE (128*1024)
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 0
|
||||
|
||||
/* Hook function related definitions. */
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||
|
||||
/* Run time and task stats gathering related definitions. */
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||
|
||||
/* Co-routine related definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES 1
|
||||
|
||||
/* Software timer related definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH 1024
|
||||
|
||||
/* Interrupt nesting behaviour configuration. */
|
||||
/*
|
||||
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||
*/
|
||||
|
||||
/* SMP port only */
|
||||
#define configNUMBER_OF_CORES 1
|
||||
#define configTICK_CORE 0
|
||||
#define configRUN_MULTIPLE_PRIORITIES 0
|
||||
|
||||
/* RP2040 specific */
|
||||
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||
|
||||
#include <assert.h>
|
||||
/* Define to trap errors during development. */
|
||||
#define configASSERT(x) assert(x)
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_xTaskAbortDelay 1
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
#define INCLUDE_xQueueGetMutexHolder 1
|
||||
|
||||
/* A header file that defines trace macro can be included here. */
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
105
Source/HC-04.c
Normal file
105
Source/HC-04.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "HC-04.h"
|
||||
#include "common.h"
|
||||
|
||||
uint8_t HC04_DATA[1024] = { 0 };
|
||||
|
||||
int HC04_DATA_LEN = 0;
|
||||
|
||||
int HC_04_UART_INIT(int pio)
|
||||
{
|
||||
// 初始化UART
|
||||
if (pio == 1) {
|
||||
uint tx_offset = pio_add_program(HC_04_PIO, &uart_tx_program);
|
||||
uart_tx_program_init(HC_04_PIO, HC_04_PIO_SM_TX, tx_offset, HC_04_PIO_TX_PIN, HC_04_PIO_SERIAL_BAUD);
|
||||
|
||||
uint rx_offset = pio_add_program(HC_04_PIO, &uart_rx_program);
|
||||
uart_rx_program_init(HC_04_PIO, HC_04_PIO_SM_RX, rx_offset, HC_04_PIO_RX_PIN, HC_04_PIO_SERIAL_BAUD);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HC_04_PIO_UART_TX_DATA(PIO pio, uint sm, char *DATA, int DATA_LEN)
|
||||
{
|
||||
for (int i = 0; i < DATA_LEN; i++) {
|
||||
uart_tx_program_putc(pio, sm, DATA[i]);
|
||||
sleep_ms(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HC_04_PIO_UART_RX_DATA(PIO pio, uint sm, uint8_t * DATA, int DATA_LEN)
|
||||
{
|
||||
char c = '\0';
|
||||
int received_count = 0;
|
||||
int timeout_ms = 1000; // 设置较长的超时时间
|
||||
|
||||
while (received_count < DATA_LEN && timeout_ms > 0) {
|
||||
if (uart_rx_program_available(pio, sm)) {
|
||||
c = uart_rx_program_getc(pio, sm);
|
||||
DATA[received_count++] = c;
|
||||
//printf("0x%X ", c);
|
||||
} else {
|
||||
// 没有接收到数据,继续等待
|
||||
sleep_ms(2);
|
||||
timeout_ms--;
|
||||
}
|
||||
}
|
||||
|
||||
if (received_count == 0) {
|
||||
// 没有接收到有效数据
|
||||
return -1;
|
||||
}
|
||||
|
||||
return received_count;
|
||||
}
|
||||
|
||||
void HC_04_UART_WRITE(void *p)
|
||||
{
|
||||
(void)p;
|
||||
/*
|
||||
AT+RESET // 重启
|
||||
AT+RX // 查询模块多个参数
|
||||
|
||||
*/
|
||||
|
||||
char _CMD0[] = "AT+RX"; // 查询
|
||||
|
||||
// 发送数据
|
||||
HC_04_PIO_UART_TX_DATA(HC_04_PIO, HC_04_PIO_SM_TX, _CMD0, sizeof(_CMD0));
|
||||
|
||||
}
|
||||
|
||||
void HC_04_UART_READ(void *p)
|
||||
{
|
||||
(void)p;
|
||||
//printf("HC-04 Module\n");
|
||||
|
||||
memset(HC04_DATA, 0, 1024);
|
||||
if (0 >= HC_04_PIO_UART_RX_DATA(HC_04_PIO, HC_04_PIO_SM_RX, HC04_DATA, 270)) {
|
||||
;
|
||||
} else {
|
||||
if (0 < strlen((char *)HC04_DATA)) {
|
||||
printf("%s\n", HC04_DATA);
|
||||
memset(HC04_DATA, 0, 1024);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HC_04(void *p)
|
||||
{
|
||||
(void)p;
|
||||
HC_04_UART_INIT(1);
|
||||
while (1) {
|
||||
HC_04_UART_WRITE(NULL);
|
||||
HC_04_UART_READ(NULL);
|
||||
|
||||
printf("\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
36
Source/HC-04.h
Normal file
36
Source/HC-04.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef HC_04_H
|
||||
#define HC_04_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "uart_rx.pio.h"
|
||||
#include "uart_tx.pio.h"
|
||||
|
||||
#define HC_04_PIO pio0
|
||||
#define HC_04_PIO_TX_PIN 12 // 接 HC-04 (RX) PIN (需要反着接)
|
||||
#define HC_04_PIO_RX_PIN 13 // 接 HC-04 (TX) PIN
|
||||
#define HC_04_PIO_SM_TX 2
|
||||
#define HC_04_PIO_SM_RX 3
|
||||
#define HC_04_PIO_SERIAL_BAUD 9600
|
||||
|
||||
extern int HC_04_UART_INIT();
|
||||
extern void HC_04_UART_WRITE(void *p);
|
||||
extern void HC_04_UART_READ(void *p);
|
||||
extern void HC_04(void *p);
|
||||
|
||||
#endif
|
||||
256
Source/IM1253B.c
Normal file
256
Source/IM1253B.c
Normal file
@@ -0,0 +1,256 @@
|
||||
#include "IM1253B.h"
|
||||
#include "common.h"
|
||||
|
||||
int Read_ID = 0x01;
|
||||
unsigned char Tx_Buffer[8];
|
||||
unsigned char Rx_Buffer[40];
|
||||
unsigned char read_enable, receive_finished, receive_number;
|
||||
unsigned long Voltage_data, Current_data, Power_data, Energy_data, Pf_data, CO2_data, Temperature_data, Hz_data;
|
||||
int sec;
|
||||
|
||||
int IM1253B_INIT(void)
|
||||
{
|
||||
uint tx_offset = pio_add_program(IM1253B_PIO, &uart_tx_program);
|
||||
uart_tx_program_init(IM1253B_PIO, IM1253B_PIO_SM_TX, tx_offset, IM1253B_PIO_TX_PIN, IM1253B_PIO_SERIAL_BAUD);
|
||||
|
||||
uint rx_offset = pio_add_program(IM1253B_PIO, &uart_rx_program);
|
||||
uart_rx_program_init(IM1253B_PIO, IM1253B_PIO_SM_RX, rx_offset, IM1253B_PIO_RX_PIN, IM1253B_PIO_SERIAL_BAUD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IM1253B_PIO_UART_TX_DATA(PIO pio, uint sm, uint8_t * DATA, int DATA_LEN)
|
||||
{
|
||||
|
||||
for (int i = 0; i < DATA_LEN; i++) {
|
||||
uart_tx_program_putc(pio, sm, DATA[i]);
|
||||
sleep_ms(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IM1253B_PIO_UART_RX_DATA(PIO pio, uint sm, uint8_t * DATA, int DATA_LEN)
|
||||
{
|
||||
char c = '\0';
|
||||
int received_count = 0;
|
||||
int timeout_ms = 1000; // 设置较长的超时时间
|
||||
|
||||
while (received_count < DATA_LEN && timeout_ms > 0) {
|
||||
if (uart_rx_program_available(pio, sm)) {
|
||||
c = uart_rx_program_getc(pio, sm);
|
||||
DATA[received_count++] = c;
|
||||
//printf("0x%X ", c);
|
||||
/*
|
||||
// 此处不能要对于 IM1253B
|
||||
if (c == '\n') {
|
||||
// 接收到换行符,停止接收数据
|
||||
break;
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
// 没有接收到数据,继续等待
|
||||
sleep_ms(2);
|
||||
timeout_ms--;
|
||||
}
|
||||
}
|
||||
|
||||
if (received_count == 0) {
|
||||
// 没有接收到有效数据
|
||||
return -1;
|
||||
}
|
||||
|
||||
return received_count;
|
||||
}
|
||||
|
||||
unsigned int calccrc(unsigned char crcbuf, unsigned int crc)
|
||||
{
|
||||
unsigned char i;
|
||||
unsigned char chk;
|
||||
crc = crc ^ crcbuf;
|
||||
for (i = 0; i < 8; i++) {
|
||||
chk = (unsigned char)(crc & 1);
|
||||
crc = crc >> 1;
|
||||
crc = crc & 0x7fff;
|
||||
if (chk == 1)
|
||||
crc = crc ^ 0xa001;
|
||||
crc = crc & 0xffff;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned int chkcrc(unsigned char *buf, unsigned char len)
|
||||
{
|
||||
unsigned char hi, lo;
|
||||
unsigned int i;
|
||||
unsigned int crc;
|
||||
crc = 0xFFFF;
|
||||
for (i = 0; i < len; i++) {
|
||||
crc = calccrc(*buf, crc);
|
||||
buf++;
|
||||
}
|
||||
hi = (unsigned char)(crc % 256);
|
||||
lo = (unsigned char)(crc / 256);
|
||||
crc = (((unsigned int)(hi)) << 8) | lo;
|
||||
return crc;
|
||||
}
|
||||
|
||||
void Print_data(void)
|
||||
{
|
||||
|
||||
float voltage_value = (float)Voltage_data * 0.0001;
|
||||
printf("电压: %.2f V\n", voltage_value);
|
||||
|
||||
float current_data = (float)Current_data * 0.0001;
|
||||
printf("电流: %.2f A\n", current_data);
|
||||
|
||||
float power_data = (float)Power_data * 0.0001;
|
||||
printf("功率: %.2f W\n", power_data);
|
||||
|
||||
float energy_data = (float)Energy_data * 0.0001;
|
||||
printf("电能: %.4f KWH\n", energy_data);
|
||||
|
||||
float pf_data = (float)Pf_data * 0.001;
|
||||
printf("功率因数: %.2f \n", pf_data);
|
||||
|
||||
float cO2_data = (float)CO2_data * 0.0001;
|
||||
printf("二氧化碳: %.2f KG\n", cO2_data);
|
||||
|
||||
printf("温度: %.2f ℃\n", (float)Temperature_data * 0.01);
|
||||
printf("频率: %.2f HZ\n", (float)Hz_data * 0.01);
|
||||
|
||||
printf("\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Analysis_data(void)
|
||||
{
|
||||
union crcdata {
|
||||
unsigned int word16;
|
||||
unsigned char byte[2];
|
||||
} crcnow;
|
||||
|
||||
if (receive_finished == 1) // 接收完成
|
||||
{
|
||||
receive_finished = 0;
|
||||
|
||||
if (Rx_Buffer[0] == Read_ID) // 确认 ID 正确
|
||||
{
|
||||
crcnow.word16 = chkcrc(Rx_Buffer, receive_number - 2); // receive_number 是接收数据总长度
|
||||
if ((crcnow.byte[0] == Rx_Buffer[receive_number - 1]) && (crcnow.byte[1] == Rx_Buffer[receive_number - 2])) // 确认 CRC 校验正确
|
||||
{
|
||||
Voltage_data = (((unsigned long)(Rx_Buffer[3])) << 24) | (((unsigned long)(Rx_Buffer[4])) << 16) | (((unsigned long)(Rx_Buffer[5])) << 8) | Rx_Buffer[6];
|
||||
Current_data = (((unsigned long)(Rx_Buffer[7])) << 24) | (((unsigned long)(Rx_Buffer[8])) << 16) | (((unsigned long)(Rx_Buffer[9])) << 8) | Rx_Buffer[10];
|
||||
Power_data = (((unsigned long)(Rx_Buffer[11])) << 24) | (((unsigned long)(Rx_Buffer[12])) << 16) | (((unsigned long)(Rx_Buffer[13])) << 8) | Rx_Buffer[14];
|
||||
Energy_data = (((unsigned long)(Rx_Buffer[15])) << 24) | (((unsigned long)(Rx_Buffer[16])) << 16) | (((unsigned long)(Rx_Buffer[17])) << 8) | Rx_Buffer[18];
|
||||
Pf_data = (((unsigned long)(Rx_Buffer[19])) << 24) | (((unsigned long)(Rx_Buffer[20])) << 16) | (((unsigned long)(Rx_Buffer[21])) << 8) | Rx_Buffer[22];
|
||||
CO2_data = (((unsigned long)(Rx_Buffer[23])) << 24) | (((unsigned long)(Rx_Buffer[24])) << 16) | (((unsigned long)(Rx_Buffer[25])) << 8) | Rx_Buffer[26];
|
||||
Temperature_data = (((unsigned long)(Rx_Buffer[27])) << 24) | (((unsigned long)(Rx_Buffer[28])) << 16) | (((unsigned long)(Rx_Buffer[29])) << 8) | Rx_Buffer[30];
|
||||
Hz_data = (((unsigned long)(Rx_Buffer[31])) << 24) | (((unsigned long)(Rx_Buffer[32])) << 16) | (((unsigned long)(Rx_Buffer[33])) << 8) | Rx_Buffer[34];
|
||||
|
||||
Print_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 电能清零
|
||||
void Electric_energy_(int *sec)
|
||||
{
|
||||
|
||||
uint8_t RETURN_DATA[8] = { 0 };
|
||||
uint8_t ELE_ZRRO[13] = { 0x01, 0x10, 0x00, 0x4B, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0xB6, 0x2C };
|
||||
|
||||
// 假如从开机算起60秒后
|
||||
if (*sec >= 3) {
|
||||
printf("电能清零\n");
|
||||
IM1253B_PIO_UART_TX_DATA(IM1253B_PIO, IM1253B_PIO_SM_TX, ELE_ZRRO, 13);
|
||||
sleep_ms(100);
|
||||
|
||||
IM1253B_PIO_UART_RX_DATA(IM1253B_PIO, IM1253B_PIO_SM_RX, RETURN_DATA, 8);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
printf("0x%X ", RETURN_DATA[i]);
|
||||
}
|
||||
sleep_ms(100);
|
||||
|
||||
*sec = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void read_data(void)
|
||||
{
|
||||
static int i = 0;
|
||||
union crcdata {
|
||||
unsigned int word16;
|
||||
unsigned char byte[2];
|
||||
} crcnow;
|
||||
|
||||
if (read_enable == 1) // 到时间抄读模块,抄读间隔 1 秒钟(或其他)
|
||||
{
|
||||
read_enable = 0;
|
||||
Tx_Buffer[0] = Read_ID; //模块的 ID 号,默认 ID 为 0x01
|
||||
Tx_Buffer[1] = 0x03;
|
||||
Tx_Buffer[2] = 0x00;
|
||||
Tx_Buffer[3] = 0x48;
|
||||
Tx_Buffer[4] = 0x00;
|
||||
Tx_Buffer[5] = 0x08;
|
||||
crcnow.word16 = chkcrc(Tx_Buffer, 6);
|
||||
Tx_Buffer[6] = crcnow.byte[1]; //CRC 效验低字节在前
|
||||
Tx_Buffer[7] = crcnow.byte[0];
|
||||
|
||||
// 发送数据
|
||||
IM1253B_PIO_UART_TX_DATA(IM1253B_PIO, IM1253B_PIO_SM_TX, Tx_Buffer, 8);
|
||||
sleep_ms(10);
|
||||
|
||||
// 接收数据
|
||||
uint8_t _DATA[37] = { 0 };
|
||||
IM1253B_PIO_UART_RX_DATA(IM1253B_PIO, IM1253B_PIO_SM_RX, _DATA, 37);
|
||||
for (i = 0; i <= 37 - 1; i++) {
|
||||
//printf("0x%X ", _DATA[i]);
|
||||
Rx_Buffer[i] = _DATA[i];
|
||||
}
|
||||
sleep_ms(10);
|
||||
}
|
||||
}
|
||||
|
||||
void IM1253B(void *p)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
IM1253B_INIT();
|
||||
while (1) {
|
||||
printf("IM1253B\n");
|
||||
|
||||
/*
|
||||
// 官方软件内部按钮发送的数据
|
||||
// 电能清零 TX[13]:01 10 00 4B 00 02 04 00 00 00 00 B6 2C
|
||||
// RX[8]:01 10 00 4B 00 02 31 DE
|
||||
|
||||
// 读取 TX[8]:00 03 00 01 00 04 14 18
|
||||
// RX[13]:01 03 08 02 35 01 08 41 30 01 05 44 BD (直流模块)
|
||||
|
||||
// 设置 TX[11]:00 10 00 04 00 01 02 01 05 6B D7
|
||||
// RX[8]:01 10 00 04 00 01 40 08
|
||||
*/
|
||||
|
||||
// 发送
|
||||
read_enable = 1;
|
||||
read_data();
|
||||
sleep_ms(10);
|
||||
|
||||
// 发送完成后接收数据并处理
|
||||
receive_number = 37;
|
||||
receive_finished = 1;
|
||||
Analysis_data();
|
||||
|
||||
// 打印处理后的数据
|
||||
//Print_data();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
35
Source/IM1253B.h
Normal file
35
Source/IM1253B.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef IM1253B_H
|
||||
#define IM1253B_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
|
||||
#include "uart_rx.pio.h"
|
||||
#include "uart_tx.pio.h"
|
||||
|
||||
#define IM1253B_PIO pio0
|
||||
#define IM1253B_PIO_TX_PIN 19 // 接 IM1253B (RX) PIN (需要反着接)
|
||||
#define IM1253B_PIO_RX_PIN 20 // 接 IM1253B (TX) PIN
|
||||
#define IM1253B_PIO_SM_TX 0
|
||||
#define IM1253B_PIO_SM_RX 1
|
||||
#define IM1253B_PIO_SERIAL_BAUD 4800
|
||||
|
||||
extern int IM1253B_INIT(void);
|
||||
extern void IM1253B(void *p);
|
||||
|
||||
#endif
|
||||
70
Source/PN532.c
Normal file
70
Source/PN532.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "PN532.h"
|
||||
|
||||
int PN532_INIT(void)
|
||||
{
|
||||
// 初始化UART
|
||||
uart_init(UART0, BAUD_RATE);
|
||||
gpio_set_function(UART0_TX_PIN, GPIO_FUNC_UART);
|
||||
gpio_set_function(UART0_RX_PIN, GPIO_FUNC_UART);
|
||||
uart_set_hw_flow(UART0, false, false);
|
||||
uart_set_format(UART0, DATA_BITS, STOP_BITS, PARITY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PN532(void *p)
|
||||
{
|
||||
(void)p;
|
||||
PN532_INIT();
|
||||
|
||||
while (1) {
|
||||
printf("PN532 Module\n");
|
||||
|
||||
uint8_t PN532_DATA[270] = { 0 };
|
||||
//int PN532_DATA_LEN = 0;
|
||||
|
||||
// 24
|
||||
// 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 03 FD D4 14 01 17 00
|
||||
uint8_t _CMD0[24] = { 0X55, 0X55, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0XFF, 0X03, 0XFD, 0XD4, 0X14, 0X01, 0X17, 0X00 };
|
||||
|
||||
// 11
|
||||
// 00 00 FF 04 FC D4 4A 02 00 E0 00
|
||||
uint8_t _CMD1[11] = { 0X00, 0X00, 0XFF, 0X04, 0XFC, 0XD4, 0X4A, 0X02, 0X00, 0XE0, 0X00 };
|
||||
|
||||
uart_write_blocking(UART0, _CMD0, 24);
|
||||
sleep_ms(100);
|
||||
uart_read_blocking(UART0, PN532_DATA, 15);
|
||||
/*
|
||||
for (int i = 0; i < 15; i++) {
|
||||
printf("0X%X ", PN532_DATA[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
*/
|
||||
memset(PN532_DATA, 0, 270);
|
||||
|
||||
uart_write_blocking(UART0, _CMD1, 11);
|
||||
sleep_ms(100);
|
||||
uart_read_blocking(UART0, PN532_DATA, 6);
|
||||
/*
|
||||
for (int i = 0; i < 6; i++) {
|
||||
printf("0X%X ", PN532_DATA[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
*/
|
||||
memset(PN532_DATA, 0, 270);
|
||||
|
||||
uart_read_blocking(UART0, PN532_DATA, 19);
|
||||
/*
|
||||
for (int i = 0; i < 19; i++) {
|
||||
printf("0X%X ", PN532_DATA[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
*/
|
||||
|
||||
printf("UID: 0X%X 0X%X 0X%X 0X%X\r\n", PN532_DATA[14 - 1], PN532_DATA[15 - 1], PN532_DATA[16 - 1], PN532_DATA[17 - 1]);
|
||||
|
||||
printf("\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
return;
|
||||
}
|
||||
28
Source/PN532.h
Normal file
28
Source/PN532.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef PN532_H
|
||||
#define PN532_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/pio.h"
|
||||
#include "uart_tx.pio.h"
|
||||
#include "uart_rx.pio.h"
|
||||
|
||||
#define UART0 uart0
|
||||
#define BAUD_RATE 115200
|
||||
#define DATA_BITS 8
|
||||
#define STOP_BITS 1
|
||||
#define PARITY UART_PARITY_NONE
|
||||
#define UART0_TX_PIN 1 // PN532 SDA (TX) PIN
|
||||
#define UART0_RX_PIN 0 // PN532 SCL (RX) PIN
|
||||
|
||||
extern int PN532_INIT(void);
|
||||
extern void PN532(void *p);
|
||||
|
||||
#endif
|
||||
61
Source/common.c
Normal file
61
Source/common.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "common.h"
|
||||
|
||||
void vApplicationMallocFailedHook(void)
|
||||
{
|
||||
/* Called if a call to pvPortMalloc() fails because there is insufficient
|
||||
free memory available in the FreeRTOS heap. pvPortMalloc() is called
|
||||
internally by FreeRTOS API functions that create tasks, queues, software
|
||||
timers, and semaphores. The size of the FreeRTOS heap is set by the
|
||||
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
|
||||
|
||||
/* Force an assert. */
|
||||
configASSERT((volatile void *)NULL);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)
|
||||
{
|
||||
(void)pcTaskName;
|
||||
(void)pxTask;
|
||||
|
||||
/* Run time stack overflow checking is performed if
|
||||
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
|
||||
function is called if a stack overflow is detected. */
|
||||
|
||||
/* Force an assert. */
|
||||
configASSERT((volatile void *)NULL);
|
||||
}
|
||||
|
||||
void vApplicationTickHook(void)
|
||||
{
|
||||
#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 0
|
||||
{
|
||||
/* The full demo includes a software timer demo/test that requires
|
||||
prodding periodically from the tick interrupt. */
|
||||
#if (mainENABLE_TIMER_DEMO == 1)
|
||||
vTimerPeriodicISRTests();
|
||||
#endif
|
||||
|
||||
/* Call the periodic queue overwrite from ISR demo. */
|
||||
#if (mainENABLE_QUEUE_OVERWRITE == 1)
|
||||
vQueueOverwritePeriodicISRDemo();
|
||||
#endif
|
||||
|
||||
/* Call the periodic event group from ISR demo. */
|
||||
#if (mainENABLE_EVENT_GROUP == 1)
|
||||
vPeriodicEventGroupsProcessing();
|
||||
#endif
|
||||
|
||||
/* Call the code that uses a mutex from an ISR. */
|
||||
#if (mainENABLE_INTERRUPT_SEMAPHORE == 1)
|
||||
vInterruptSemaphorePeriodicTest();
|
||||
#endif
|
||||
|
||||
/* Call the code that 'gives' a task notification from an ISR. */
|
||||
#if (mainENABLE_TASK_NOTIFY == 1)
|
||||
xNotifyTaskFromISR();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
16
Source/common.h
Normal file
16
Source/common.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef COMMOM_H
|
||||
#define COMMOM_H
|
||||
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include "hardware/pio.h"
|
||||
|
||||
static inline bool uart_rx_program_available(PIO pio, uint sm)
|
||||
{
|
||||
return !pio_sm_is_rx_fifo_empty(pio, sm);
|
||||
}
|
||||
|
||||
#endif
|
||||
92
Source/main.c
Normal file
92
Source/main.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/* Scheduler include files. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* Standard demo includes. */
|
||||
#include "TimerDemo.h"
|
||||
#include "QueueOverwrite.h"
|
||||
#include "EventGroupsDemo.h"
|
||||
#include "IntSemTest.h"
|
||||
#include "TaskNotify.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "common.h"
|
||||
#include "IM1253B.h"
|
||||
#include "PN532.h"
|
||||
#include "EC800M_GPS.h"
|
||||
#include "EC800M_4G.h"
|
||||
#include "HC-04.h"
|
||||
|
||||
void Led_Blinky(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
|
||||
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
gpio_put(LED_PIN, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
gpio_put(LED_PIN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Read_Onboard_Temperature(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
|
||||
adc_init();
|
||||
adc_set_temp_sensor_enabled(true);
|
||||
adc_select_input(4); // Input 4 is the onboard temperature sensor.
|
||||
|
||||
while (1) {
|
||||
const float conversionFactor = 3.3f / (1 << 12);
|
||||
|
||||
float adc = (float)adc_read() * conversionFactor;
|
||||
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
|
||||
|
||||
printf("Onboard temperature %.02f°C %.02f°F\n", tempC, (tempC * 9 / 5 + 32));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
stdio_init_all();
|
||||
sleep_ms(1000);
|
||||
//set_sys_clock_khz(250000, true);
|
||||
|
||||
BaseType_t xReturned;
|
||||
TaskHandle_t Led_Blinky_xHandle = NULL;
|
||||
TaskHandle_t Read_Onboard_Temperature_xHandle = NULL;
|
||||
TaskHandle_t IM1253B_xHandle = NULL;
|
||||
TaskHandle_t EC800M_4G_xHandle = NULL;
|
||||
TaskHandle_t PN532_xHandle = NULL;
|
||||
TaskHandle_t HC_04_xHandle = NULL;
|
||||
|
||||
// 板载LED闪烁
|
||||
xReturned = xTaskCreate(Led_Blinky, "Blinky task", 512, NULL, tskIDLE_PRIORITY, &Led_Blinky_xHandle);
|
||||
|
||||
// CPU温度
|
||||
xReturned = xTaskCreate(Read_Onboard_Temperature, "Temperature task", 512, NULL, tskIDLE_PRIORITY, &Read_Onboard_Temperature_xHandle);
|
||||
|
||||
// IM1253B 电压、功率模块
|
||||
xReturned = xTaskCreate(IM1253B, "IM1253B task", 1024, NULL, tskIDLE_PRIORITY, &IM1253B_xHandle);
|
||||
|
||||
// EC800M 4G 模块
|
||||
xReturned = xTaskCreate(EC800M_4G, "EC800M 4G task", 1024, NULL, tskIDLE_PRIORITY, &EC800M_4G_xHandle);
|
||||
|
||||
// PN532 NFC 模块
|
||||
xReturned = xTaskCreate(PN532, "PN532 task", 512, NULL, tskIDLE_PRIORITY, &PN532_xHandle);
|
||||
|
||||
// HC-04 蓝牙模块
|
||||
xReturned = xTaskCreate(HC_04, "HC_04 task", 512, NULL, tskIDLE_PRIORITY, &HC_04_xHandle);
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
return 0;
|
||||
}
|
||||
17
Source/main.h
Normal file
17
Source/main.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
|
||||
#endif
|
||||
94
Source/uart_rx.pio
Normal file
94
Source/uart_rx.pio
Normal file
@@ -0,0 +1,94 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
.program uart_rx_mini
|
||||
|
||||
; Minimum viable 8n1 UART receiver. Wait for the start bit, then sample 8 bits
|
||||
; with the correct timing.
|
||||
; IN pin 0 is mapped to the GPIO used as UART RX.
|
||||
; Autopush must be enabled, with a threshold of 8.
|
||||
|
||||
wait 0 pin 0 ; Wait for start bit
|
||||
set x, 7 [10] ; Preload bit counter, delay until eye of first data bit
|
||||
bitloop: ; Loop 8 times
|
||||
in pins, 1 ; Sample data
|
||||
jmp x-- bitloop [6] ; Each iteration is 8 cycles
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
static inline void uart_rx_mini_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
pio_gpio_init(pio, pin);
|
||||
gpio_pull_up(pin);
|
||||
|
||||
pio_sm_config c = uart_rx_mini_program_get_default_config(offset);
|
||||
sm_config_set_in_pins(&c, pin); // for WAIT, IN
|
||||
// Shift to right, autopush enabled
|
||||
sm_config_set_in_shift(&c, true, true, 8);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
// SM transmits 1 bit per 8 execution cycles.
|
||||
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
||||
|
||||
.program uart_rx
|
||||
|
||||
; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and
|
||||
; break conditions more gracefully.
|
||||
; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
|
||||
|
||||
start:
|
||||
wait 0 pin 0 ; Stall until start bit is asserted
|
||||
set x, 7 [10] ; Preload bit counter, then delay until halfway through
|
||||
bitloop: ; the first data bit (12 cycles incl wait, set).
|
||||
in pins, 1 ; Shift data bit into ISR
|
||||
jmp x-- bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles
|
||||
jmp pin good_stop ; Check stop bit (should be high)
|
||||
|
||||
irq 4 rel ; Either a framing error or a break. Set a sticky flag,
|
||||
wait 1 pin 0 ; and wait for line to return to idle state.
|
||||
jmp start ; Don't push data if we didn't see good framing.
|
||||
|
||||
good_stop: ; No delay before returning to start; a little slack is
|
||||
push ; important in case the TX clock is slightly too fast.
|
||||
|
||||
|
||||
% c-sdk {
|
||||
static inline void uart_rx_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
pio_gpio_init(pio, pin);
|
||||
gpio_pull_up(pin);
|
||||
|
||||
pio_sm_config c = uart_rx_program_get_default_config(offset);
|
||||
sm_config_set_in_pins(&c, pin); // for WAIT, IN
|
||||
sm_config_set_jmp_pin(&c, pin); // for JMP
|
||||
// Shift to right, autopush disabled
|
||||
sm_config_set_in_shift(&c, true, false, 32);
|
||||
// Deeper FIFO as we're not doing any TX
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
// SM transmits 1 bit per 8 execution cycles.
|
||||
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
static inline char uart_rx_program_getc(PIO pio, uint sm) {
|
||||
// 8-bit read from the uppermost byte of the FIFO, as data is left-justified
|
||||
io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm] + 3;
|
||||
while (pio_sm_is_rx_fifo_empty(pio, sm))
|
||||
tight_loop_contents();
|
||||
return (char)*rxfifo_shift;
|
||||
}
|
||||
|
||||
%}
|
||||
61
Source/uart_tx.pio
Normal file
61
Source/uart_tx.pio
Normal file
@@ -0,0 +1,61 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
.program uart_tx
|
||||
.side_set 1 opt
|
||||
|
||||
; An 8n1 UART transmit program.
|
||||
; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin.
|
||||
|
||||
pull side 1 [7] ; Assert stop bit, or stall with line in idle state
|
||||
set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks
|
||||
bitloop: ; This loop will run 8 times (8n1 UART)
|
||||
out pins, 1 ; Shift 1 bit from OSR to the first OUT pin
|
||||
jmp x-- bitloop [6] ; Each loop iteration is 8 cycles.
|
||||
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
static inline void uart_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx, uint baud) {
|
||||
// Tell PIO to initially drive output-high on the selected pin, then map PIO
|
||||
// onto that pin with the IO muxes.
|
||||
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_gpio_init(pio, pin_tx);
|
||||
|
||||
pio_sm_config c = uart_tx_program_get_default_config(offset);
|
||||
|
||||
// OUT shifts to right, no autopull
|
||||
sm_config_set_out_shift(&c, true, false, 32);
|
||||
|
||||
// We are mapping both OUT and side-set to the same pin, because sometimes
|
||||
// we need to assert user data onto the pin (with OUT) and sometimes
|
||||
// assert constant values (start/stop bit)
|
||||
sm_config_set_out_pins(&c, pin_tx, 1);
|
||||
sm_config_set_sideset_pins(&c, pin_tx);
|
||||
|
||||
// We only need TX, so get an 8-deep FIFO!
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
// SM transmits 1 bit per 8 execution cycles.
|
||||
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
static inline void uart_tx_program_putc(PIO pio, uint sm, char c) {
|
||||
pio_sm_put_blocking(pio, sm, (uint32_t)c);
|
||||
}
|
||||
|
||||
static inline void uart_tx_program_puts(PIO pio, uint sm, const char *s) {
|
||||
while (*s)
|
||||
uart_tx_program_putc(pio, sm, *s++);
|
||||
}
|
||||
|
||||
%}
|
||||
Reference in New Issue
Block a user