华大单片机-串口通讯多字节

华大单片机—串口通信

1.串口通信基本原理

(1)串口通信原理:

这部分可以百度,或者去看下野火的stm32教程,串口通信原理基本一样。这里不再详细讲解!

(2)华大的串口通信:

这部分可以直接看用户手册的UART章节。我保证肯定讲的比我详细。里面也有各种寄存器,学会看数据手册是非常重要的,我也是工作后才明白的。之前学习stm32都是看别人的例程跑通就移植了。怎么实现压根不管。第一次用这种资料比较少的单片机,你能依靠的只有几百页的手册了。一遍不懂看多几遍。。。

(3)简单介绍下:

发送数据
发送数据时,与 UARTx_SCON.REN 的值无关,将所发送数据写入 UARTx_SBUF 寄存器中,数据就会从 TXD 移出(低位在先,高位在后)。

接收数据
接收数据时,需将 UARTx_SCON.REN 位置 1,并将 UARTx_ISR.RI 位清 0。开始接收 RXD 上数据(低位在先,高位在后),当接收完毕,可以从 UARTx_SBUF 寄存器读出。

接收缓存
通用 UART(UART0/1)接收端有一个帧长度(8/9bits)的接收缓存,也就是说当一帧数据接收完毕后,接收缓存中的数据会被一直保持,直到下一帧数据的 Stop 位接收完毕后,接收缓存才会更新为新一帧数据。

发送缓存
通用 UART(UART0/1)发送端不支持发送缓存。如果在发送数据过程中,填写UARTx_SBUF 寄存器,将会破坏当前正在发送数据。软件应该避免这种操作。

(4)多字符发送:

基本串口通信用demo都可以跑通的,但是demo都是基于一个字节的,在实际使用中,通常都是发送多个字节或者字符串的。因此我参考了野火的多字节发送和字符串发送的代码。自己写了多字节发送代码。

用中断方式,自己写发送函数,开启发送中断,只需发送第一个字节,发送完成后会进入串口中断,中断中判断是否是发送中断,如果是,判断是否已经发送最后一个字节,如果是,关闭发送中断;如果没有发送到最后一个字节,则发送下一个字节。2.查询方式,从第一个字节循环发送,查询等待发送完成标志,判断是否是最后一个字节,不是,循环发送一个字节,是最后一个字节,退出循环。要发送的内容可以放在一个数组之中 -

2.初始化代码

//串口0引脚配置代码
void Uart_PortInit(void)
{
    stc_gpio_cfg_t stcGpioCfg;

    DDL_ZERO_STRUCT(stcGpioCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟

    ///<URART0_TX
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(URART0_port, URART0_TX, &stcGpioCfg);
    Gpio_SetAfMode(URART0_port, URART0_TX, GpioAf1);         //配置PA08 端口为URART0_TX

    ///<RX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(URART0_port, URART0_RX, &stcGpioCfg);
    Gpio_SetAfMode(URART1_port, URART0_RX, GpioAf1);          //配置PA10 端口为URART0_RX
	
	
}
//串口配置初始化
void App_Uart0Cfg(void)
{
    stc_uart_cfg_t    stcCfg;

    DDL_ZERO_STRUCT(stcCfg);

    ///< 开启外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<使能uart0模块时钟

    ///<UART Init
    stcCfg.enRunMode        = UartMskMode1;          ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;           ///<1bit停止位
    //stcCfg.enMmdorCk        = UartMskEven;           ///<偶检验
    stcCfg.stcBaud.u32Baud  = 9600;                  ///<波特率9600
    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq(); ///<获得外设时钟(PCLK)频率值
    Uart_Init(M0P_UART0, &stcCfg);                   ///<串口初始化

    ///<UART中断使能
    Uart_ClrStatus(M0P_UART0,UartRC);                ///<清接收请求
    Uart_ClrStatus(M0P_UART0,UartTC);                ///<清接收请求
    Uart_EnableIrq(M0P_UART0,UartRxIrq);             ///<使能串口接收中断
    Uart_EnableIrq(M0P_UART0,UartTxIrq);             ///<使能串口接收中断
    EnableNvic(UART0_IRQn, IrqLevel3, TRUE);       ///<系统中断使能	
}

3.发送代码:

串口发送是非常重要的,在日常的调试代码中,或者单片机与其他物联网设备通讯一般都可以通过串口。

//发送一个字节
void Uart_SendByte(M0P_UART_TypeDef* UARTx,uint8_t ch)
{
	Uart_SendDataIt(UARTx,ch);//库函数的发送一个字节
	while( Uart_GetStatus(UARTx, UartTxe)== FALSE);
    //获取TXE的状态,一直等于FLASE=0,表示TX buffer非空
}


//发送字符串
void Uart_SendString(M0P_UART_TypeDef* UARTx,char *str)
{
	 uint8_t k=0;
	do
	{
		
//		if(Uart_GetStatus(M0P_UART0,UartTC))
//		{
//			Uart_ClrStatus(M0P_UART0, UartTC);
//		}
		Uart_SendByte(UARTx,*(str+k));//循环发送一个字节一个字节的发
		k++;
	
	}while(*(str+k)!='\0');//直至遇到字符串结束符 '\0'
	
}

在这里插入图片描述

是不是很简单,如果看过野火的UART部分,就回发现思路是一样的,哈哈!我的就是参考着写的。。根据上面(4)的原理写的。采用的是查询方式,,比较好理解。一开始按stm32的思路去写老是错误,后来静下心来想了下。

4.接收中断代码

串口不仅发送非常重要,串口接收也是非常重要的,在项目中有时候需要从串口传入参数,或者在网络通讯中,服务器通过联网设备在通过串口直接发送指令给单片机操作对应的外设。串口接收一般采用的是中断的方式。直接看代码!

//UART0中断函数代码
void Uart0_IRQHandler(void)
{
		//先存储在数组中。
	if(Uart_GetStatus(M0P_UART0, UartRC))         // RC 接收完成为真,UART0数据接收,有数据来了
    {
			Uart_ClrStatus(M0P_UART0, UartRC);        //清掉接收中断标志位 置0,为下次继续接收做准备
        RxBuffer[u8RxCnt] = Uart_ReceiveData(M0P_UART0);   	//接收数据字节,把缓存寄存器的值存储在数组中
				//Uart_SendDataIt(M0P_UART0,temp[u8RxCnt]); 				//接收回显
				u8RxCnt++;			//依次存储
    }
		//u8RxCnt=0;//置0,方便下次重复以上操作
		if(Uart_GetStatus(M0P_UART0,UartTC))  // TC 发送完成为真,发送完成一个字节
		{
			Uart_ClrStatus(M0P_UART0,UartTC); //清掉发送中断标志位。置0
			
		}

}

5.总结:

基本到此,华大单片机的串口通讯是没用问题了,能实现基本的串口收发以及多字节收发。至于映射-printf打印,有兴趣可以搞下。

串口是计算机上一种非常通用设备通信的协议(不要与通用串行总线Universal Serial Bus或者USB混淆)。大多数计算机包含两个基于RS232的串口串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS- 232口。同时,串口通信协议也可以用于获取远程采集设备的数据。 串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。 典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配: a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为 14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是 GPIB设备的通信。 b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语 “包”指任何通信的情况。 c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。 d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值