1800|0

6960

帖子

11

TA的资源

版主

楼主
 

【平头哥RVB2601创意应用开发】模拟UART一 [复制链接]

 

【前言】RVB2601的项目中我原来考虑需要3个串口,一个用于接收电压、电流、功率监测的数据,另一路用于接收无线发过来的温湿度,第三路用于LOG的输入输出,现在LOG输入占用了UART0,UART1的默认端口被SPI占用了。所以只能考虑用IO来实现UART。

【可行性分析】模拟UART我以前没有实现过,但是听说过,所以说只有想不到的,没有做不到的。而且最近在试用报告中的@qq4988已经实现了,有了他的文章给了我信心。经过查阅资料,很多基于51、stm32的都有过成功实现用IO模拟实现了串口的例子。我想应该能实现这一功能。

【知识储备】

1、认真的学习了RISC-V RVB2601 初体验--第3节--IO模拟串口完成 https://bbs.eeworld.com.cn/thread-1196608-1-1.html这篇文章N篇,也留了言,可能是作者工作原因没有空回复。

2、网上学习了基于51、stm32的文章,最有借鉴意义的是这篇:单片机IO口模拟UART串口通信_C语言中文网 (biancheng.net)。大家如果有兴趣也可以去读一下这篇帖子。

3、串口发送的时序图学习,我这里只应用8位,1位停止位,无较验,波特率为9600.

4、再加上自己的N种设想。。。略去一万字。。。

【实现需要的外设】

1、两个IO,经仔佃查看原理图后,只能拿三个LED来开刀,PA7、PA25、PA4这三个IO,其实也可以用两个KEY,但是KEY可能还有其他的用处,所以用PA7作为TX,PA25作为RX来用。

2、定时器,由于串口需要精确的延时来实现,借鉴网友的经验,特别是@qq4988的经验,用定时器timer1来实现。

【实现的思路】

1、初始化PA7为TX,gpio输出,初始化PA25为中断输入。

2、初始化定时器,设置为0.104为一次中断触发,为波特率9600。

3、创建定时器中断回调函数。

【实现步聚】

1、定义发送结收结构体,用于发送接收:

enum{
    VM_SEND,
    VM_REVC,
    IDLE    
};

typedef struct {
    uint8_t vm_uart_dir;//发送,接收
    uint8_t vm_uart_tx_byte;//发送数据
    uint8_t vm_uart_tx_bit;
    uint8_t vm_uart_tx_flag;
    uint8_t vm_uart_rx_byte;
    uint8_t vm_uart_rx_irq;
    uint8_t vm_uart_rx_count;
    uint8_t vm_uart_tx_buf[UART_MAX_LEN];
    uint8_t vm_uart_rx_buf[UART_MAX_LEN];
} _io_uart_para;
 

2、初始化IO、中断、定时器:

/*模拟UART IO初始化*/
void io_uart_init(void)
{
    csi_pin_set_mux(PA7, PIN_FUNC_GPIO);
    csi_pin_set_mux(PA25, PIN_FUNC_GPIO);

    csi_gpio_pin_init(&io_uart0_tx, PA7);
	csi_gpio_pin_init(&io_uart0_rx,PA25);
    
	csi_gpio_pin_dir(&io_uart0_tx,GPIO_DIRECTION_OUTPUT);
	csi_gpio_pin_dir(&io_uart0_rx,GPIO_DIRECTION_INPUT);

    csi_gpio_pin_mode(&io_uart0_tx,GPIO_MODE_OPEN_DRAIN);
    csi_gpio_pin_mode(&io_uart0_rx,GPIO_MODE_PULLNONE);
	
	csi_gpio_pin_attach_callback(&io_uart0_rx,io_uart0_rx_interrupt_handler,NULL);
	csi_gpio_pin_irq_mode(&io_uart0_rx,GPIO_IRQ_MODE_FALLING_EDGE);
	csi_gpio_pin_irq_enable(&io_uart0_rx,true);
	io_uart_para.vm_uart_dir = IDLE;
	io_uart_para.vm_uart_tx_bit = 0;
	io_uart_para.vm_uart_rx_count = 0;
	io_uart0_tx_write_High;
}
//定时器初始化
void timer1_init(void)
{
	int ret = -1;
	timer1.port = TIMER1_PORT_NUM;
	
	//timer1.config.period = 1000000; //1s
	timer1.config.period = 104;//0.104ms
	timer1.config.reload_mode = TIMER_RELOAD_AUTO;
	timer1.config.cb = timer1_handler;
	
	ret = hal_timer_init(&timer1);
	if(ret != 0)
	{
		printf("timer1 init error !\n");
	}
	else{
		hal_timer_stop(&timer1);
	}
	
}

3、定时器发送函数:

//定时器回调函数
void timer1_handler(void *arg)
{
	if(io_uart_para.vm_uart_dir == VM_SEND)//如果是发送
	{
		if(io_uart_para.vm_uart_tx_bit <=8 ) //如果发送不足8位
		{
			if((io_uart_para.vm_uart_tx_byte & 0x01) == 0x01 ){
				io_uart0_tx_write_High;
			}else{
				io_uart0_tx_write_Low;
			}
			io_uart_para.vm_uart_tx_byte>>=1;
		}
		else{
			if(io_uart_para.vm_uart_tx_bit > 8){
				io_uart0_tx_write_High;
				io_uart0_rx_timer_disable();
				io_uart_para.vm_uart_tx_flag = 0; //设置为发送完毕
				io_uart_para.vm_uart_dir = IDLE;
				
			}
		}
		io_uart_para.vm_uart_tx_bit ++;
		
	}
	
}

4、发送测试:

int main(void)
{
	
    board_yoc_init();
    LOGD(TAG, "%s\n", aos_get_app_version());
    oled_init();
    io_uart_init();
	timer1_init();
    LOGD(TAG, "led and key test");

    while (1) {
		io_uart_para.vm_uart_tx_byte = 0x01;
		io_uart_para.vm_uart_tx_bit = 0;
		io_uart_para.vm_uart_dir = VM_SEND;
		io_uart0_tx_write_Low;
		io_uart0_rx_timer_enable();
		while(io_uart_para.vm_uart_dir == IDLE);
		//io_uart0_tx_write_High;
		LOGD(TAG, "send 0x1end");
		//aos_msleep(2000);
		io_uart0_tx_write_Low;
		io_uart_para.vm_uart_tx_byte = 0x02;
		io_uart_para.vm_uart_tx_bit = 0;
		io_uart_para.vm_uart_dir = VM_SEND;
		io_uart0_rx_timer_enable();
		while(io_uart_para.vm_uart_dir == IDLE);
		LOGD(TAG, "send 0x2end");
		//aos_msleep(2000);
		io_uart0_tx_write_Low;
		io_uart_para.vm_uart_tx_byte = 0x03;
		io_uart_para.vm_uart_tx_bit = 0;
		io_uart_para.vm_uart_dir = VM_SEND;
		io_uart0_rx_timer_enable();
		while(io_uart_para.vm_uart_dir == IDLE);
		LOGD(TAG, "send 0x3end");
		aos_msleep(2000);
	
		
    }
    return 0;
}

【实验结果】:

 【讨论】这次摸拟串口发送数据还只是成功的三分之一不到,还有串口接收功能没写完。在这里自己发出来,一来是再复习一遍,二来也是为记录。

下一步,对发送函数进行封装,再努力把串口接收功能写出来。

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表