ESP32S3单线软件串口

1.头文件 

/*
 * one_wire_serial.h
 *
 *  Created on: 2024年5月9日
 *  Author: Administrator
 */

#ifndef MAIN_ONE_WIRE_SERIAL_H_
#define MAIN_ONE_WIRE_SERIAL_H_
#include <stdint.h>

void one_wire_timer_init(void);
uint8_t one_wire_serial_send_data(uint8_t* data, uint32_t len);
void wire_gpio_init(void);
void test_gpio_init(void);
void report_wire_info(void);


#endif /* MAIN_ONE_WIRE_SERIAL_H_ */

2.源文件

/*
 * one_wire_serial.c
 *
 *  Created on: 2024年5月9日
 *      Author: Administrator
 */
#include "one_wire_serial.h"
#include "driver/timer.h"
#include "driver/gpio.h"
#include "string.h"

#define ENABLE_TEST_GPIO 0

#define WIRE_GPIO_PIN GPIO_NUM_11
#define TEST_GPIO_PIN GPIO_NUM_5


#define ONE_WIRE_SERIAL_TX_BUF_SIZE 1024
#define ONE_WIRE_SERIAL_RX_BUF_SIZE 1024
#define ONE_WIRE_SERIAL_BAUD 9600
#define ONE_WIRE_SERIAL_PLUS_TIME (1000000 / 9600) //US

enum{
	ONE_WIRE_SERIAL_RX = 0,
	ONE_WIRE_SERIAL_TX,
};



typedef struct{
	/*发送数据缓存*/
	uint8_t tx_buf[ONE_WIRE_SERIAL_TX_BUF_SIZE];
	/*发送字节数据计数*/
	uint32_t tx_count;
	/*发送长度*/
	uint32_t tx_len;
	/*发送bit数据计数*/
	uint8_t tx_bit_count;
	//uint8_t tx_flag;

	/*接收数据缓存*/
	uint8_t rx_buf[ONE_WIRE_SERIAL_RX_BUF_SIZE];
	/*已接收数据长度*/
	uint32_t rx_len;
	/*接收bit数据计数*/
	uint8_t rx_bit_count;
	/*接收起始标志位*/
	uint8_t rx_start_flag;

	uint8_t status;
}one_wire_serial_t;

one_wire_serial_t oserial = {
		.rx_bit_count = 0,
		.rx_len = 0,
		.rx_start_flag = 0,
		.status = ONE_WIRE_SERIAL_RX,
		.tx_bit_count = 0,
		.tx_count = 0,
		.tx_len = 0,
};

#define TIMER_DIVIDER         	(80)  //  Hardware timer clock divider

#define WIRE_TIMER_GROUP 		TIMER_GROUP_0
#define WIRE_TIMER				TIMER_0


//开始定时器工作,设定中断时间us
void one_wire_timer_start(uint32_t us)
{
	timer_set_alarm_value(WIRE_TIMER_GROUP, WIRE_TIMER, us);
	timer_set_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, 0);
	timer_start(WIRE_TIMER_GROUP, WIRE_TIMER);
}
//停止定时器工作
void one_wire_timer_stop(void)
{
	timer_pause(WIRE_TIMER_GROUP, WIRE_TIMER);
}

//设置gpio电平
void set_wire_level(uint8_t level)
{
	gpio_set_level(WIRE_GPIO_PIN, level);
}

//0:输入 1:输出
void wire_init(uint8_t mode)
{
	if(mode)
	{
		gpio_intr_disable(WIRE_GPIO_PIN);
		gpio_set_direction(WIRE_GPIO_PIN, GPIO_MODE_OUTPUT);
	}
	else
	{
		gpio_set_direction(WIRE_GPIO_PIN, GPIO_MODE_INPUT);
		gpio_intr_enable(WIRE_GPIO_PIN);
	}
}

//获取gpio电平
uint8_t get_wire_level(void)
{
	return gpio_get_level(WIRE_GPIO_PIN);
}

//翻转测试gpio电平
void test_gpio_toggle(void)
{
	static uint8_t status = 0;
	status = !status;
	gpio_set_level(TEST_GPIO_PIN, status);
}

//gpio中断
void IRAM_ATTR wire_int(void* arg)
{
	/*处于接收状态且没有开始接收*/
	if((oserial.status == ONE_WIRE_SERIAL_RX) && (oserial.rx_start_flag == 0))
	{
		oserial.rx_start_flag = 1;

		one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME / 2);
#if ENABLE_TEST_GPIO
		test_gpio_toggle();
#endif
	}
	//printf("init.\r\n");
}


/*测试gpio初始化*/
void test_gpio_init(void)
{
	gpio_config_t io_conf = {
	    .pin_bit_mask = (1ULL << TEST_GPIO_PIN), 	// 选择
	    .mode = GPIO_MODE_OUTPUT,           			// 设置为输入模式
	    .pull_up_en = GPIO_PULLUP_ENABLE,  			// 禁用上拉
	    .pull_down_en = GPIO_PULLDOWN_DISABLE, 		// 启用下拉
	    .intr_type = GPIO_INTR_DISABLE      		// 禁用中断
	};
	gpio_config(&io_conf);
	test_gpio_toggle();
}


/*串口gpio初始化*/
void wire_gpio_init(void)
{
	gpio_config_t io_conf = {
	    .pin_bit_mask = (1ULL << WIRE_GPIO_PIN), 	// 选择GPIO4
	    .mode = GPIO_MODE_INPUT,           			// 设置为输入模式
	    .pull_up_en = GPIO_PULLUP_ENABLE,  			// 禁用上拉
	    .pull_down_en = GPIO_PULLDOWN_DISABLE, 		// 启用下拉
	    .intr_type = GPIO_INTR_NEGEDGE      		// 禁用中断
	};
	gpio_config(&io_conf);
	gpio_install_isr_service(0);
	gpio_isr_handler_add(WIRE_GPIO_PIN, wire_int, NULL);
#if ENABLE_TEST_GPIO
	test_gpio_init();
#endif
}

/*定时器中断收发处理*/
void IRAM_ATTR one_wire_serial_handle(void* args)
{
	if(oserial.status == ONE_WIRE_SERIAL_TX)//发送模式
	{
		/*有数据要发送,且还未发完*/
		if((oserial.tx_len > 0) && (oserial.tx_count < oserial.tx_len))
		{
			/*发送起始bit*/
			if(oserial.tx_bit_count == 0)
			{
				set_wire_level(0);
				oserial.tx_bit_count++;
			}/*发送停止bit*/
			else if(oserial.tx_bit_count == 9)
			{
				set_wire_level(1);
				oserial.tx_count++;
				oserial.tx_bit_count = 0;
			}
			else/*发送数据8bit*/
			{
				set_wire_level((oserial.tx_buf[oserial.tx_count] & (1 << (oserial.tx_bit_count - 1))) ? 1 : 0 );
				oserial.tx_bit_count++;
			}
		}
		else
		{
			oserial.tx_len = 0;
			oserial.tx_bit_count = 0;
			oserial.tx_count = 0;
			oserial.status = ONE_WIRE_SERIAL_RX;
			one_wire_timer_stop();
			wire_init(0);
		}
	}
	else
	{
		if(oserial.rx_bit_count == 0)
		{
			if(get_wire_level() == 0) //起始bit
			{
				oserial.rx_bit_count++;
				one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME);
#if ENABLE_TEST_GPIO
				test_gpio_toggle();
#endif
			}
			else
			{
				one_wire_timer_stop();
				oserial.rx_start_flag = 0;
			}
		}
		else if(oserial.rx_bit_count == 9)
		{
			if(get_wire_level() == 1) //停止bit
			{
				oserial.rx_len++;
				oserial.rx_bit_count = 0;
			}
			else
			{
				oserial.rx_bit_count = 0;
			}
#if ENABLE_TEST_GPIO
			test_gpio_toggle();
#endif
			one_wire_timer_stop();
			wire_init(0);
			oserial.rx_start_flag = 0;
		}
		else
		{
#if ENABLE_TEST_GPIO
			test_gpio_toggle();
#endif
			if(get_wire_level())
			{
				oserial.rx_buf[oserial.rx_len] |= (1 << (oserial.rx_bit_count - 1));
			}
			else
			{
				oserial.rx_buf[oserial.rx_len] &= ~(1 << (oserial.rx_bit_count - 1));
			}

			oserial.rx_bit_count++;
		}

	}
}
uint8_t one_wire_serial_send_data(uint8_t* data, uint32_t len)
{
	if(oserial.tx_len == 0)
	{
		wire_init(1);
		oserial.tx_len = len;
		oserial.tx_bit_count = 0;
		oserial.tx_count = 0;
		oserial.status = ONE_WIRE_SERIAL_TX;
		memcpy(oserial.tx_buf, data, len);
		one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME);
		return 1;
	}
	return 0;
}

void one_wire_timer_init(void)
{
	 timer_config_t config = {
	        .divider = TIMER_DIVIDER,
	        .counter_dir = TIMER_COUNT_UP,
	        .counter_en = TIMER_PAUSE,
	        .alarm_en = TIMER_ALARM_EN,
	        .auto_reload = TIMER_AUTORELOAD_EN,
	    }; // default clock source is APB
	timer_init(WIRE_TIMER_GROUP, WIRE_TIMER, &config);
	timer_set_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, 0);
	timer_isr_callback_add(WIRE_TIMER_GROUP, WIRE_TIMER, one_wire_serial_handle, NULL, 0);
}


void report_wire_info(void)
{
	uint64_t value = 0;
	timer_get_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, &value);
	//printf("timer count:%lld.\r\n", value);
	//printf("oserial.tx_len:%d.\r\n", oserial.tx_len);
	//printf("oserial.rx_len:%d.\r\n", oserial.rx_len);
	//printf("get_wire_level:%d.\r\n", get_wire_level());
	if(oserial.rx_len > 0)
	{
		printf("%.*s.\r\n", oserial.rx_len, oserial.rx_buf);
		//printf("oserial.rx_buf:%.*s.\r\n", oserial.rx_len, oserial.rx_buf);
		//printf("oserial.rx_buf[0]:%x.\r\n", oserial.rx_buf[0]);
		oserial.rx_len = 0;
	}
}

注意事项,目前只支持1bit起始位1bit结束位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章