代码生成器配置和软件UART的实现

由于mcu内部资源限制,在应用中会出现uart接口不够用的情况,如果uart使用的波特率不太高,而且系统中的负荷不是很大的情况就可以使用端口来模拟uart的收发,下文是一个在r5f100le(rl78)上的具体的实现方法,这里略去工程的建立过程,相应的驱动程序细节可以参考代码生成器生成的代码,这里只重点讲述代码生成器配置和软件uart的实现。
一、硬件资源准备
01一个具有外部边沿中断功能的io口来做uart的rxd端口,下面是一个配置的例子,在这里我们使用p137(intp0),在代码生成器里选择intp0为下降沿中断,中断优先级可以任意设置。
02一个普通的输出口来作为uart的txd端口。这里选择p43端口,设置端口输出高。
03两个可以产生中断、可以随时关闭启动、定时间隔可以任意设定的定时器,一个发送定时器用于发送数据,一个接收定时器用于接收数据。
将接收定时器的定时间隔初始化为1位数据的时长的一半,比如波特率2400,1位为416.6us,那么定时器设置为416.6us/2=208.3us,在这里我们使用了timer的channel 1
将发送定时器的定时间隔设置为1位数据时长,比如波特率2400,1位为416.6us,那么定时器设置为416.6us,在这里我们使用timer的channel 0。
二、uart接收功能的实现
01接收的软件实现
接收时我们需要写两个中断函数,在中断里完成数据的接收,接收完毕后设置一个标志,在主循环中根据标志来判断数据是否接收完毕。初始化时需要打开边沿中断,关闭定时器中断。
1)边沿中断函数处理
当下降沿中断到来时,在边沿中断函数里启动接收定时器,关闭边沿中断。具体程序如下:
左右滑动查看完整内容
void softuart_rece_port_fall_edge_callback(void){  softuart_rece_state = 0;//接收定时器进入次数计数清零  uart_port_intp_stop();// 关闭边沿中断  start_uart_rece_timer();//打开接收定时器中断}  
这个函数放到r_cg_intc_user.c内
2)接收定时器中断函数
每奇数次进入中断时(第1,3,5…)进行rxd端口的采样并保存数据,同时根据我们的要求进行移位操作(比如lsb或msb,数据长度是几位),在偶数次进入中断时就直接退出,当数据接收完成后设置标志,同时关闭接收定时器中断,打开边沿中断中断,具体程序如下,这里我是用的8位数据长度和1个停止位:
左右滑动查看完整内容
void softuart_rece_timer_callback(void){static __saddr uint8_t uartrece_shift_reg;  softuart_rece_state++;//进入次数++  if(softuart_rece_state==1)//接收start位  {    //check start bit    if(1==get_uart_rece_port())    {      //start bit error      uartrece_shift_reg = 0;      stop_uart_rece_timer();      uart_port_intp_start();    }  }  else if (softuart_rece_state>= 1;    if(1==get_uart_rece_port())    {      uartrece_shift_reg |= 0x80;    }  }  else if(softuart_rece_state>=19)//接收停止位  {    //stop bit sample sampling point 19    stop_uart_rece_timer();//关闭接收定时器    uart_port_intp_start();//打开下降沿中断    if(uartrece_end_fg ==0)    {      uartrece_data = uartrece_shift_reg;      uartrece_end_fg =1;//设置接收完毕标志    }  }}  
这个程序要放到r_cg_timer_user.c内
3)在主循环里调用如下函数来判断是否收到数据
左右滑动查看完整内容
uint8_t get_softuart_rece(uint8_t * buff){  if(uartrece_end_fg==1)  {    uartrece_end_fg =0;    *buff = uartrece_data;//将数据放入接收缓冲区    return 1;//说明收到数据  }  return 0;}  
三、uart发送功能的实现
01发送软件的实现
发送时需要写一个发送定时器中断函数,在中断里完成数据发送,发送完成后设置一个标志,在主循环中判断,初始化时需要关闭发送定时器,中断的代码如下:
左右滑动查看完整内容
void softuart_send_callback(void){  softuart_send_state++;  if(softuart_send_state==10)//发送停止位  {    //sampling point 10 stop bit    softuart_send_port_h();  }  else if(softuart_send_state>10)//等待停止位发送完毕  {    //>11 stop bit send finished    softuart_send_state=0;    stop_uart_send_timer();  }  else//发送数据  {    //samplimng point 2,3,4,5,6,7,8,9    if(0!=(uartsend_shift_reg&1))    {      softuart_send_port_h();    }    else    {      softuart_send_port_l();    }    uartsend_shift_reg >>= 1;  }}  
这个程序要放到r_cg_timer_user.c内
当需要发送时,先将发送端口设置为低电平,然后开启发送定时器,如果正在发送返回发送错误。具体的操作代码如下:
左右滑动查看完整内容
uint8_t softuart_send(uint8_t data){  if(softuart_send_state!=0)return 0;//数据没有发送完毕  softuart_send_state = 1;  di();  softuart_send_port_l();     //发送起始位  uartsend_shift_reg=data;//将要发送的数据放到移位寄存器  start_uart_send_timer();//启动uart发送定时器  ei();  return 1;}  
四、整个程序的初始化
由于相应硬件的初始化程序在r_systeminit已经调用过了,所以我们只用调用启动程序就行了,为了方便程序的修改,用宏定义重新定义了接口部分。
左右滑动查看完整内容
#define start_uart_rece_timer() r_tau0_channel1_start()#define stop_uar_rece_timer() r_tau0_channel1_stop()#define uart_port_intp_start()        r_intc0_start()#define uart_port_intp_stop()        r_intc0_stop()#define get_uart_rece_port()        p13_bit.no7#define start_uart_send_timer() r_tau0_channel0_start()#define stop_uart_send_timer()  r_tau0_channel0_stop()#define softuart_send_port_h()        {p4_bit.no3 = 1;}#define softuart_send_port_l()        {p4_bit.no3 = 0;}  
如果想要修改使用的硬件资源只用修改宏定义即可。
在使用软件uart之前需要先调用一下如下初始化函数。
左右滑动查看完整内容
void softuart_int(void){  stop_uart_send_timer();//停止发送定时器  stop_uart_rece_timer();//停止接收定时器  uart_port_intp_stop();  // 边沿中断接收停止  softuart_send_port_h(); // txd端口设置为高  uart_port_intp_start();  // 允许rxd端口的下降沿中断  softuart_send_state = 0;  softuart_rece_state = 0;  uartrece_end_fg = 0;}  
注意
1)使用上述方法就可以实现一个软件的uart操作,但是使用过程中不能有长时间的关闭中断操作,如果有的话会影响程序的执行。
2)如果通讯波特率发生变化需要修改定时器的定时值。


如何做一部基于STM32F4的手持式游戏机
快讯:汉诺威工业展起跑,聚焦人工智能与5G
华人卫视携手玉银能公司打造区块链+艺术品资产化交易服务平台
CEE国际消费电子展多管齐下打造行业发展年度盛典
OPPO开发者大会2021 colorOS的AON全天候视觉感知服务
代码生成器配置和软件UART的实现
虹科与Dimetix合作三年, 致力提供精确的测距解决方案
工业自控流程对传感器有哪些不同需求?
台湾远翔电源管理芯片
霍尔电流传感器如何测量电流
小米mix2什么时候上市 小米mix2价格是多少?
如何用常用的耐压绝缘测试测量AC/DC转换器隔离电压
中国互联网行业错失一个超级大BOSS平台,该高兴还是该懊悔呢?
微软推出一系列MagSafe游戏配件
基于单/双核Zynq的GigaExpress SBC PCIe卡
基于Vitis AI的ADAS目标识别
高通摊上大事,被台湾罚款51亿,估计只是说说而已
【节能学院】用电预付费系统在工业园区物业管理中的应用
晶体知识:位错的基本类型和特征
基于SiC功率模块的高效逆变器设计方案