典型uart协议为什么只有三个地址引脚

CC2540的HAL层UART学习笔记(待续)
& & 本文以TI的BLE1.3.2示例工程SimpleBLEPeripheral作关于UART的备忘笔记。
& & 首先看hal_board_cfg.h,其中有关于底层驱动的默认配置:
/* Driver Configuration */
/* Set to TRUE enable H/W TIMER usage, FALSE disable it */
#ifndef HAL_TIMER
#define HAL_TIMER FALSE
/* Set to TRUE enable ADC usage, FALSE disable it */
#ifndef HAL_ADC
#define HAL_ADC TRUE
/* Set to TRUE enable DMA usage, FALSE disable it */
#ifndef HAL_DMA
#define HAL_DMA TRUE
/* Set to TRUE enable Flash access, FALSE disable it */
#ifndef HAL_FLASH
#define HAL_FLASH TRUE
/* Set to TRUE enable AES usage, FALSE disable it */
#ifndef HAL_AES
#define HAL_AES TRUE
#ifndef HAL_AES_DMA
#define HAL_AES_DMA TRUE
/* Set to TRUE enable LCD usage, FALSE disable it */
#ifndef HAL_LCD
#define HAL_LCD TRUE
/* Set to TRUE enable LED usage, FALSE disable it */
#ifndef HAL_LED
#define HAL_LED TRUE
#if (!defined BLINK_LEDS) && (HAL_LED == TRUE)
#define BLINK_LEDS
/* Set to TRUE enable KEY usage, FALSE disable it */
#ifndef HAL_KEY
#define HAL_KEY TRUE
/* Set to TRUE enable UART usage, FALSE disable it */
#ifndef HAL_UART
#if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2)
#define HAL_UART TRUE
#define HAL_UART FALSE
#if HAL_UART
// Always prefer to use DMA over ISR.
#if HAL_DMA
#ifndef HAL_UART_DMA
#if (defined ZAPP_P1) || (defined ZTOOL_P1)
#define HAL_UART_DMA
#elif (defined ZAPP_P2) || (defined ZTOOL_P2)
#define HAL_UART_DMA
#define HAL_UART_DMA
#ifndef HAL_UART_ISR
#define HAL_UART_ISR
#ifndef HAL_UART_ISR
#if (defined ZAPP_P1) || (defined ZTOOL_P1)
#define HAL_UART_ISR
#elif (defined ZAPP_P2) || (defined ZTOOL_P2)
#define HAL_UART_ISR
#define HAL_UART_ISR
#ifndef HAL_UART_DMA
#define HAL_UART_DMA
// Used to set P2 priority - USART0 over USART1 if both are defined.
#if ((HAL_UART_DMA == 1) || (HAL_UART_ISR == 1))
#define HAL_UART_PRIPO
#define HAL_UART_PRIPO
#define HAL_UART_DMA
#define HAL_UART_ISR
#if !defined HAL_UART_SPI
#define HAL_UART_SPI
#ifdef __cplusplus
#endif /* HAL_BOARD_CFG_H */
& & 工程中默认的配置是:
INT_HEAP_LEN=3072
HALNODEBUG
OSAL_CBTIMER_NUM_TASKS=1
HAL_AES_DMA=TRUE
HAL_DMA=TRUE
POWER_SAVING
xPLUS_BROADCASTER
HAL_LCD=TRUE
HAL_LED=FALSE
& & 可知只定义了HAL_DMA=TRUE,根据hal_board_cfg.h文件可知默认下工程并没有使能UART。若要使能UART,需要定义HAL_UART=TRUE。此时,HAL_DMA=TRUE且HAL_UART=TRUE,根据配置文件可知此时宏HAL_UART_DMA的值为1。修改完成后编译,编译器警告:
& & 原来这个示例工程包含了按键的应用,从配置文件里面我们发现:
/* Set to TRUE enable KEY usage, FALSE disable it */
#ifndef HAL_KEY
#define HAL_KEY TRUE
& & 好吧,没办法,只能在编译选项里面定义HAL_KEY=FALSE(因为我不太喜欢动官方的源文件,所以就没有直接在配置文件里面修改)。再次编译,OK!没问题,完美通过。
& & 下面着重探究下UART在DMA使能下的具体操作。
& & 前面已经提到,定义HAL_UART=1后,配置文件默认使用UART的DMA方式,IRS中断方式是关闭的,另外可别同时在同一个Port(P0或P1)使能UART和SPI哦!
& & 实际上,宏HAL_UART_DMA并不是两个值(TRUE or FALSE),而是有3个值(0,1,2)。当HAL_UART_DMA=1时,程序使用UART0的第一引脚配置(Alt 1)。
& & 工程默认情况下是有低功耗的,在POWER_SAVING已定义的情况下,DMA_PM=1,使能CT脚的下降沿触发中断。CT、RT脚是当UART使用流控制时的引脚,CT脚为输入、RT脚为输出,连接方法是:
& & 数据手册是这么说的:
由于数据手册没有对流控制的详细过程进行说明,而网上对流控制的一般解释又不太一样,我老是搞混,现在我根据一个比较合理的理解来解释一下。举个例子,如果A要向B发送数据,A会将自己的RTS脚置0,B的CTS脚接收到0电平后,将判断是否可以接收数据,如果可以,则将B的RTS脚置0,则A的CTS脚信号则为0,表示A可以发送数据,否则RTS脚置1。即:某设备要发送数据,它先将自己的RTS脚置0,然后等待自己的CTS脚为0,之后再发送数据。
& & 下面来做个小实验,使用HAL的API向串口发送数据:
& & 1.使用UART0的ALT1配置实现与电脑串口的通信,对电脑发来的数据进行透明回复。
& & & & 首先是要设置相应的宏定义:
HAL_UART=TRUE
HAL_KEY=FALSE
& & 然后,在SimpleBLEPeripheral_ProcessEvent()函数的SBP_START_DEVICE_EVT事件中添加代码:
UART Port open
halUARTCfg_
config.baudRate = HAL_UART_BR_115200;
config.flowControl = FALSE;
config.callBackFunc = uartRxCB;
HalUARTOpen(HAL_UART_PORT_0, &config);
/* 打开串口 */
& & 这样就成功打开了串口0,并且使用115200波特率,并且关闭流控制,并将自定义的回调函数uartRxCB()传递给HAL,当有关UART的事件发生后可以进行相应的处理。那么这个回调函数怎么写呢,暂且不急,我们先来了解下UART在DMA方式下的工作原理(想了解CC2540 DMA的工作原理可以点击这里)。
& & 首先是对UART的DMA进行初始化,具体的配置为:
UART TX通道
通道号 & & & & & & 4
SRCADDR & & & & & &实时设置
DESTADDR & & & & & 0x70C1(UART0的发送寄存器地址)
VLEN & & & & & & & 使用LEN字段来规定需要传输的字节数
LEN & & & & & & & &最大传输字节数
WORDSIZE & & & & & 以8-bit为单位传输
TMODE & & & & & & &single模式
TRIG & & & & & & & UART发送完毕后触发
SRCINC & & & & & & 传输完一字节数据后源地址+1byte
DESTINC & & & & & &传输完一字节数据后目的地址不变 IRQMASK & & & & & &使能DMA中断
M8 & & & & & & & & LEN字段所有比特位用于表示字节数
PRIORITY & & & & & 高优先级
UART RX通道
通道号 & & & & & & 3
SRCADDR & & & & & &0x70C1(UART0的接收寄存器地址)
DESTADDR & & & & & 接收缓冲区
VLEN & & & & & & & 使用LEN字段来规定需要传输的字节数
LEN & & & & & & & &最大传输字节数
WORDSIZE & & & & & 以16-bit为单位传输
TMODE & & & & & & &single-repeated模式
TRIG & & & & & & & UART接收完毕后触发
SRCINC & & & & & & 传输完一字节数据后源地址不变
DESTINC & & & & & &传输完一字节数据后目的地址+1(16-bit) IRQMASK & & & & & &禁止DMA中断
M8 & & & & & & & & LEN字段所有比特位用于表示字节数
PRIORITY & & & & & 高优先级
& & 由此可知,当UART接收到数据后,是不会产生中断干预CPU的,而在UART发送数据时,每次完成发送都会产生中断干预CPU,中断处理代码如下:
/******************************************************************************
HalDMAInit
DMA Interrupt Service Routine
*****************************************************************************/
HAL_ISR_FUNCTION( halDmaIsr, DMA_VECTOR )
HAL_ENTER_ISR();
DMAIF = 0;
#if (((defined HAL_UART_DMA) && (HAL_UART_DMA != 0)) || \
((defined HAL_UART_SPI) && (HAL_UART_SPI != 0)))
if (HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX))
HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX);
extern void HalUARTIsrDMA(void);
HalUARTIsrDMA();
#if (defined HAL_IRGEN) && (HAL_IRGEN == TRUE)
if ( HAL_IRGEN == TRUE && HAL_DMA_CHECK_IRQ( HAL_IRGEN_DMA_CH ) )
HAL_DMA_CLEAR_IRQ( HAL_IRGEN_DMA_CH );
HalIrGenDmaIsr();
CLEAR_SLEEP_MODE();
HAL_EXIT_ISR();
& & 其他代码我们先不管,先看主要部分HalUARTIsrDMA(),而HalUARTIsrDMA()在当前配置下最终会执行如下代码:
/******************************************************************************
HalUART_DMAIsrDMA
Handle the Tx done DMA ISR.
*****************************************************************************/
void HalUART_DMAIsrDMA(void)
#if !HAL_UART_TX_BY_ISR
if (dmaCfg.txIdx[dmaCfg.txSel])
// If there is more Tx data ready to go, re-arm the DMA immediately on it.
HalUARTArmTxDMA();
// Indicate that the Tx buffer just finished is now free (re-arming did a ^= toggle of txSel).
dmaCfg.txIdx[dmaCfg.txSel] = 0;
dmaCfg.txIdx[(dmaCfg.txSel ^ 1)] = 0;
// Indicate that the Tx buffer just finished is now free.
// Clear the CSR_TX_BYTE flag & start the txTick to allow the possibility of an immediate
// manual trigger from the next Write(), if it occurs more than one character time later.
HalUARTPollTxTrigDMA();
dmaCfg.txMT = TRUE;
// Notify CB that at least one Tx buffer is now free to use.
& & 注意到该变量dmaCfg,它其实是文件_hal_uart_dma.c文件中的一个静态全局变量,类型为:
typedef struct
&span style=&color:#3366&&uint16 rxBuf[HAL_UART_DMA_RX_MAX];
rxIdx_t rxH
rxIdx_t rxT&/span&
#if HAL_UART_DMA_IDLE
#if HAL_UART_TX_BY_ISR
uint8 txBuf[HAL_UART_DMA_TX_MAX];
volatile txIdx_t txH
txIdx_t txT
uint8 txMT;
&span style=&color:#3333&&uint8 txBuf[2][HAL_UART_DMA_TX_MAX];
txIdx_t txIdx[2];
uint8 txMT;
// Indication that at least one of two Tx buffers are free.
// ST ticks of delay to allow at least one byte-time at a given baud rate.
// Flag indicating that Tx should be manually triggered after txTick expires.
// Although all of the txVars above are modified by the Tx-done ISR, only this one should need
// the special volatile consideration by the optimizer (critical sections protect the rest).
volatile uint8 txS&/span&
&span style=&color:#3333&&halUARTCBack_t uartCB;&/span&
} uartDMACfg_t;
& & 以上是对UART在DMA方式下对数据发送的操作原理,下面介绍一下UART在DMA方式下对数据的接收处理。
& & 因为之前已经提过,当UART接收到数据,且DMA完成数据搬移后,DMA是不会触发中断干预CPU的,OSAL会在Hal_ProcessPoll()的HalUARTPoll()的HalUARTPollDMA()对UART的DMA接收BUFFER进行轮询处理,以下是代码:
/******************************************************************************
HalUARTPollDMA
Poll a USART module implemented by DMA, including the hybrid solution in which the Rx
is driven by DMA but the Tx is driven by ISR.
*****************************************************************************/
static void HalUARTPollDMA(void)
uint8 evt = 0;
#if DMA_PM
PxIEN &= ~DMA_RDYIn_BIT;
// Clear to not race with DMA_RDY_IN ISR.
if (dmaRdyIsr || HAL_UART_DMA_RDY_IN() || HalUARTBusyDMA())
// Master may have timed-out the SRDY asserted state & may need a new edge.
#if HAL_UART_TX_BY_ISR
if (!HAL_UART_DMA_RDY_IN() && (dmaCfg.txHead != dmaCfg.txTail))
if (!HAL_UART_DMA_RDY_IN() && ((dmaCfg.txIdx[0] != 0) || (dmaCfg.txIdx[1] != 0)))
HAL_UART_DMA_CLR_RDY_OUT();
dmaRdyIsr = 0;
if (dmaRdyDly == 0)
(void)osal_set_event(Hal_TaskID, HAL_PWRMGR_HOLD_EVENT);
if ((dmaRdyDly = ST0) == 0)
// Reserve zero to signify that the delay expired.
dmaRdyDly = 0xFF;
HAL_UART_DMA_SET_RDY_OUT();
else if ((dmaRdyDly != 0) && (!DMA_PM_DLY || ((uint8)(ST0 - dmaRdyDly) & DMA_PM_DLY)))
dmaRdyDly = 0;
(void)osal_set_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT);
PxIEN |= DMA_RDYIn_BIT;
#if !HAL_UART_TX_BY_ISR
HalUARTPollTxTrigDMA();
if (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
if (HAL_UART_DMA_NEW_RX_BYTE(uartRxBug))
HAL_UART_RX_IDX_T_INCR(dmaCfg.rxHead);
} while (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead));
uartRxBug = dmaCfg.rxH
dmaCfg.rxTail = dmaCfg.rxH
HAL_UART_RX_IDX_T_INCR(uartRxBug);
cnt = HalUARTRxAvailDMA();
// Wait to call until after the above DMA Rx bug work-around.
#if HAL_UART_DMA_IDLE
if (dmaCfg.rxTick)
// Use the LSB of the sleep timer (ST0 must be read first anyway) to measure the Rx timeout.
if ((ST0 - dmaCfg.rxTick) & HAL_UART_DMA_IDLE)
dmaCfg.rxTick = 0;
evt = HAL_UART_RX_TIMEOUT;
else if (cnt != 0)
if ((dmaCfg.rxTick = ST0) == 0)
// Zero signifies that the Rx timeout is not running.
dmaCfg.rxTick = 0xFF;
if (cnt != 0)
evt = HAL_UART_RX_TIMEOUT;
if (cnt &= HAL_UART_DMA_FULL)
evt |= HAL_UART_RX_FULL;
else if (cnt &= HAL_UART_DMA_HIGH)
evt |= HAL_UART_RX_ABOUT_FULL;
if (!DMA_PM && (UxUCR & UCR_FLOW))
HAL_UART_DMA_CLR_RDY_OUT();
// Disable Rx flow.
if (dmaCfg.txMT)
dmaCfg.txMT = FALSE;
evt |= HAL_UART_TX_EMPTY;
if ((evt != 0) && (dmaCfg.uartCB != NULL))
dmaCfg.uartCB(HAL_UART_DMA-1, evt);
if (DMA_PM && (dmaRdyDly == 0) && !HalUARTBusyDMA())
HAL_UART_DMA_CLR_RDY_OUT();
& & 读这段代码,头有点大了:
if (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
if (HAL_UART_DMA_NEW_RX_BYTE(uartRxBug))
HAL_UART_RX_IDX_T_INCR(dmaCfg.rxHead);
} while (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead));
uartRxBug = dmaCfg.rxH
dmaCfg.rxTail = dmaCfg.rxH
HAL_UART_RX_IDX_T_INCR(uartRxBug);
& & 这段完全没明白,HAL_UART_DMA_NEW_RX_BYTE的宏定义是
#define HAL_UART_DMA_NEW_RX_BYTE(IDX)
((uint8)DMA_PAD == HI_UINT16(dmaCfg.rxBuf[(IDX)]))
& & 其中,DMA_PAD实际就是UART外设的波特率设置寄存器U0BAUD,我很疑惑,为什么要用到U0BAUD寄存器?后来,经过仔细的在线调试才发现其中的奥秘:
& & 首先,我打开了UART,但是我没有在UART接收回调里做任何处理,之后我向设备发送2个相同的字节0xAA,在调试器里我看到:
& & 联想到DMA,因为用于UART接收的DMA通道是一次传送16-bit的数据的,然后源地址是寄存器U0BUF的地址,它只有1个字节,因此自然而然U0BAUD被'不小心'传过去了,但实际上,虽然rxBuf数组的类型是uint16的,但其实它的每个元素的低字节用于存储接收到的数据,高地址为当前U0BAUD寄存器的值。其实,U0BAUD的值被放在高8位,就是表明这个位置存放了新接收的数据而且这个数据没有被应用层处理过。有了这个线索,后面的代码就好理解了。先看函数HalUARTRxAvailDMA():
/**************************************************************************************************
HalUARTRxAvailDMA()
Calculate Rx Buffer length - the number of bytes in the buffer.
length of current Rx Buffer
**************************************************************************************************/
static uint16 HalUARTRxAvailDMA(void)
// First, synchronize the Rx tail marker with where the DMA Rx engine is working.
rxIdx_t tail = dmaCfg.rxT
if (!HAL_UART_DMA_NEW_RX_BYTE(tail))
HAL_UART_RX_IDX_T_INCR(tail);
} while (tail != dmaCfg.rxHead);
dmaCfg.rxTail =
uint16 cnt = tail - dmaCfg.rxH
// If the DMA Rx may have overrun the circular queue, investigate further.
if ((cnt == 0) && HAL_UART_DMA_NEW_RX_BYTE(tail))
/* Ascertain whether this polling is racing with the DMA Rx which may have clocked in a byte
* since walking the tail. The Rx queue has wrapped only if the byte before the head is new.
tail = dmaCfg.rxH
HAL_UART_RX_IDX_T_DECR(tail);
if (HAL_UART_DMA_NEW_RX_BYTE(tail))
if (HAL_UART_RX_FLUSH)
(void)memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*2);
uartRxBug = dmaCfg.rxH
dmaCfg.rxTail = dmaCfg.rxH
cnt = HAL_UART_DMA_RX_MAX;
else if (cnt & HAL_UART_DMA_RX_MAX)
// If the tail has wrapped at the end of the Rx queue.
cnt += HAL_UART_DMA_RX_MAX;
& & 首先要明确一点,DMA把UART接收到的数据搬移到dmaCfg.rxBuf后,
dmaCfg.rxTail和
dmaCfg.rxHead的值是不变的,所以函数的开头就需要先更新
dmaCfg.rxT
ail的值,以下代码段干的就是这个。
& & if (!HAL_UART_DMA_NEW_RX_BYTE(tail))
& & HAL_UART_RX_IDX_T_INCR(tail);
& } while (tail != dmaCfg.rxHead);
& dmaCfg.rxTail =
& & 接下来,局部变量cnt就计算出当前
dmaCfg.rxBuf有多少字节数据未处理了。
uint16 cnt = tail - dmaCfg.rxH
& & 如果我继续发数据,直到所有的
dmaCfg.rxBuf被写满:
& & 我们发现此时rxTail的值已经从下标轮询了一遍,此时if ((cnt == 0) && HAL_UART_DMA_NEW_RX_BYTE(tail))条件满足了,说明缓存已经满了,接下来的处理就是把dmaCfg.rxBuf全部设置为U0BAUD的值的取反,相当于BUFFEER清空,并设置dmaCfg.rxHead=dmaCfg.rxTail。
本分类共有文章3篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";后使用快捷导航没有帐号?
查看: 905|回复: 2
MSP430的IIC模式为什么可以任意选择引脚,而UART和SPI却不可以
在线时间24 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
MSP430的IIC模式为什么可以任意选择引脚,而UART和SPI却不可以,这是为什么呢
在线时间1895 小时
威望3807分
芯币12876枚
E金币171枚
TA的帖子TA的资源
五彩晶圆(中级), 积分 3807, 距离下一级还需 2193 积分
五彩晶圆(中级), 积分 3807, 距离下一级还需 2193 积分
IIC模式只要引脚高低电平符合i2c时序就行。SPI也是可以模拟的
SPI模式固定接SOMI、SIMO、UCLK和STE,IIC是可以任意选择I/O口作为SCL和SDA吧?&
在线时间24 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
IIC模式只要引脚高低电平符合i2c时序就行。SPI也是可以模拟的
SPI模式固定接SOMI、SIMO、UCLK和STE,IIC是可以任意选择I/O口作为SCL和SDA吧?
荣誉会员勋章
曾经的版主且威望大于2000,或对EEWORLD论坛有突出贡献的坛友
Powered by
逛了这许久,何不进去瞧瞧?stm8s串口通信(uart)
最近开始使用stm8s103k3单片机了。据说很好,确实不错。前几天已经试过了GPIO,Timer2,ADC的功能,都比较容易,唯独串口UART使用,破费周折,写出来,供大家借鉴。
我使用的是stm8s103k3,32脚单片机,这个使用手册上说了UART1,UART2,UART3。但是引脚的功能图上只有UART1,并且你打开stm8s103k.h的头文件,里面也只有UART1寄存器的定义说明。所以我认为只有UART1。既然有这个功能,那就用吧,我以为直接可以连接到电脑的串口(COM1),就可以使用了,其实不可以。单片机即使写着提供UART通讯功能,也要连接MAX232转接芯片,我就在这里耽误了许多时间。
&&&&1、使用stm8s103上的串口和计算机com口通许的硬件连接:
&&&&&2、软件设置
(1)发送数据配置
1)编程UART_CR1的M位来定义字长。
2)在UART_CR3中编程停止位的位数。
3)按下列顺序编写波特率寄存器选择要求的波特率。&&&&&&
a)UART_BRR2
&b)UART_BRR1
4)设置UART_CR2中的TEN位来使能发送
5)把要发送的数据写进UART_DR寄存器
&main.c程序如下:
"stm8s103k.h"
UART1_Init(void)
UART1_CR2=0x00;//使发送禁用TEN=0;
UART1_CR1=0x00;//设置M字长,8位数据位
UART1_CR3=0x00;//1位停止位
UART1_BRR2=0x00;//00-0d:9600(fcpu=fmaster=2MHz)
UART1_BRR1=0x0d;//00-1a::2400
UART1_CR2=0x08;
&& //fmaster=fcpu=2MHz
& &CLK_ECKR=0x00;
& &CLK_ICKR=0x01;
& &CLK_CMSR=0xe1;
&& CLK_SWR=0xe1;
&& CLK_CKDIVR=0x18;
&&&UART1_Init();
& &while (1)
&while(!(UART1_SR &
0x80));//发送寄存器数据是否转移完
&UART1_CR2=0x00;//a处
&&&&&UART1_DR=0xB6;//要发送的数据
&&&&&UART1_CR2=0x08;//b处
&&&&&while((UART1_SR
& 0x40) ==0);//发送是否完成
上面的代码是我反复实验过的,如果不加a和b处代码,则接收的数据不稳定,比如发送5,接收到的数据的串口多次开闭,则接收的数据可能是0xB6,或0x67,或0x3B.
(2)接收数据
1)编程UART_CR1的M位来定义字长。
2)在UART_CR3中编程停止位的位数。
3)按下列顺序编写波特率寄存器选择要求的波特率。
a)UART_BRR2
b)UART_BRR1
4)设置UART_CR2中的REN位来使能接收
5)读UART_DR寄存器
a)查询:查询SR中标志位RXNE (读数据寄存器非空)
b)中断:需使能CR2中的RIEN(接收中断使能)
标志位查询方式:
void UART1_Init(void)
&UART1_CR1 = 0x00; //8bit
&UART1_CR3 = 0x00;//1 stop bit
&UART1_BRR2 = 0x01;
&UART1_BRR1 = 0x1A;//4800 baud rate
&UART1_CR2 = 0x04;//enable REN
Main()函数:
(!(UART1_SR & 0x20));//Loop until the UART1 Receive Data
Register is not empty
RxBuffer& = UART1_DR; //Store the received byte in
中断方式:
void UART1_Init(void)
&UART1_CR1 = 0x00; //8bit
&UART1_CR3 = 0x00;//1 stop bit
&UART1_BRR2 = 0x01;
&UART1_BRR1 = 0x1A;//4800 baud rate
&UART1_CR2 = 0x24;//enable REN and RIEN
UART1接收中断函数:
@far @interrupt void UART1_RX_IRQHandler (void)
&& RxBuffer = UART1_DR; //Store
the received byte in RxBuffer
UART1接收中断向量(设置中断向量,即将中断服务程序的入口填写到中断向量表中)
struct interrupt_vector const _vectab[] =
& {0x82, UART1_RX_IRQHandler},
(3)特别注意波特率的计算设置方式
波特率通过配置16位除法器UART_DIV来设置
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。UM1x通用异步收发器(UART)第9章:LPC;v.00.10―11January2010ReR;Usermanual;1.如何阅读本章;所有LPC111x系列UART模块都相同;PLCC44封装下配置有引脚;2.功能特性;???????;16字节收发FIFO;寄存器位置符合’550工业标准;接收器FIFO触发点可为1、4、8和14字节;U
111x通用异步收发器(UART)第9章:LPCLPC1
v.00.10―11January2010ReRev201
Usermanual
1.如何阅读本章
所有LPC111x系列UART模块都相同。DSR、DCD和RI三个调制信号只在LQFP48和
PLCC44封装下配置有引脚。
2.功能特性
16字节收发FIFO。
寄存器位置符合’550工业标准。
接收器FIFO触发点可为1、4、8和14字节。内置波特率发生器。
UART允许软件或硬件实现流控制。支持RS-485/EIA-4859位模式。调制解调器控制。
3.引脚描述
DTR[1]DSR[1][1]
输入输入输入输入
串行输入。串行接收数据。
输出串行输出。串行发送数据。输出请求发送.RS-485方向控制引脚。输出数据终端就绪。
数据设备就绪。清除发送。数据载波检测。振铃指示
只针对LQFP48封装。
调制解调器输入DSR、DCD和RI复用在两个不同的引脚上。通过使用IOCON_LOC寄存器(见7C4.2节)可为每个功能选择LQFP48封装上引脚的位置,通过IOCON寄存器选择功能。
DTR输出对于2个引脚位置都是可用的。引脚DTR的值同时受两个位置分别驱动,功能在哪个引脚上可以通过IOCON寄存器为引脚选择功能来确定。
Semiconductors
LPC1100开发,尽在Coocox
111x通用异步收发器第9章:LPCLPC1
4.时钟和功耗控制
UART模块由AHBCLKCTRL寄存器(见表3C19)开关。外设器产生,由UARTCLKDIV寄存器所控制(见表3C21)。
UART_PCLK时钟信号能通过UARTCLKDIV寄存器来禁止(见),同时为了降低功耗还可以通过系统AHB时钟控制寄存器的第12位来关闭UART模块(见)。注释:在UART时钟被允许之前,必需在相应的IOCON寄存器对UART引脚进行配置。
5.寄存器描述
UART所包含的寄存器如表9C116组织。除数锁存访问位(DLAB)位于U0LCR[7],它用于允许对除数锁存器的访问。
Semiconductors
LPC1100开发,尽在Coocox
第9章:LPC111x通用异步收发器
U0RBRU0THRU0DLLU0DLMU0IER
只读只写读/写读/写读/写
接收器缓存寄存器,存放着下一个要读的已接受字节。发送保持寄存器。存放下一个将要被发送的字符。
除数锁存LSB。波特率除数值的最低字节。完整除数用于分数分频器,来生成波特率。
除数锁存MSB。波特率除数值的最高字节。完整除数用于分数分频器,来生成波特率。
DLAB=1DLAB=1当
DLAB=0----------------
中断允许寄存器。包含有7个独立的潜在的UART中断的允许位。
中断ID寄存器。识别出哪个中断正被挂起。
U0IIRU0FCRU0LCRU0MCRU0LSRU0MSRU0SCRU0ACR-U0FDR-U0TER-
只读只写读/写读/写只读只读读/写读/写-读/写-读/写-
0xC0x80x01C0x80x02C0xxx8
FIFO控制寄存器。控制UARTFIFO的用法和模式。线控制寄存器。包含有帧格式和间断生成的控制。Modem控制寄存器Modem状态寄存器。
线状态寄存器。包含接收和发送状态,以及线错误的标志。暂存寄存器。软件可以使用这8位临时存储空间。自动波特率控制寄存器。包含自动波特率特性的控制。保留
分数分频寄存器。为波特率分频器产生时钟输入。保留
发送允许寄存器。软件流控制时,使用该寄存器关掉UART发送器。保留
U0RS485CTRL读/写U0ADRMATCH读/写U0RS485DLYU0FIFOLVL
0x000x010x000x000x000x600x00-0x00-0x10-0x80-0x000x000x000x00
RS-485/EIA-485控制。包含配置RS-485/EIA-485模式各个方面
RS-485/EIA-485地址匹配。包含RS-485/EIA-485模式下的地址匹配值。
RS-485/EIA-485直接控制延迟。
FIFO等级寄存器。提供当前接收发送FIFO的等级数。
[1]复位值只反映在所使用位的数据。它不影响保留位内容。
Semiconductors
LPC1100开发,尽在Coocox
第9章:LPC111x通用异步收发器
5.1UART接收缓存寄存器(U0RBR-0x,当
DLAB=0,只读)
U0RBR是UART接收FIFO队列最高字节。接收FIFO队列包含了最早接收到的字符,可通过总线接口读出。LSB(位0)代表最早接收到的数据位。如果接收到的字符小于8位,未使用的MSB填充为0。
如果要访问U0RBR,U0LCR的除数锁存访问位(DLAB)必须为0。U0RBR为只读寄存器。
由于PE、FE和BI位(见表9C126)与RBRFIFO顶端的字节相对应(即下次读RBR时,读出的字节),因此,将接收的字节及其状态位成对读出的正确方法是先读U0LSR,再读U0RBR。
UART接收器缓存寄存器包含UARTRxFIFO当中最早接收到的字未定义
5.2UART发送器保持寄存器(U0THR-0x,DLAB=0,只写)
U0THR是UARTTX(发送)FIFO的最高字节。该最高字节是TXFIFO中最新的字符,可通过总线接口写入。LSB代表最先要发送的位。
如果要访问U0THR,U0LCR的除数锁存访问位(DLAB)必须为0。U0THR为只写寄存器。
LL-0x和U0DLM-5.3UART除数锁存LSB和MSB寄存器(U0D(U0DL
0x,当DLAB=1)
UART除数锁存是UART波特率发生器的一部分,并且保持使用的值,与分数分频器一起去分频UART_PCLK时钟来产生波特率时钟,波特率时钟是波特率的16倍。U0DLL和U0DLM寄存器一起构成一个16位除数,其中U0DLL包含除数的低8位,U0DLM包含除数的高8位;值0x0000被看作是0x0001,因为除数是不允许为0。当访问UART除数锁存寄存器时,U0LCR中的除数锁存访问位(DLAB)必须为1。如何选择U0DLL和U0DLM正确值,详见第9C5.15节。
写UART发送器保持寄存器将数据保存到UART发送FIFO当中。
当字节到达FIFO的最底部并且发送器就绪时,该字节将被发送。
Semiconductors
LPC1100开发,尽在Coocox
第9章:LPC111x通用异步收发器
波特率。保留
5.4UART中断允许寄存器(U0IER-0x,当DLAB=0)
U0IER用于允许UART四个中断源。
THRE中断允许
禁止RDA中断。允许RDA中断。
允许UARTTHRE中断。该中断的状态可从U0LSR[5]读出。0
RX线中断允许
--931:10-3-
0101-保留-保留
禁止THRE中断。允许THRE中断。
允许UARTRx线状态中断。该中断的状态可从U0LSR出
[4:1]中读出。
禁止Rx线状态中断。允许Rx线状态中断。
保留,用户软件不要向保留位写入1从保留位读出的值未被NA
允许自动波特率结束中断。禁止自动波特率结束中断。允许自动波特率结束中断。允许自动波特率超时中断。禁止自动波特率超时中断。允许自动波特率超时中断。
ABTOIntEn0
保留,用户软件不要向保留位写入1从保留位读出的值未被NA定义。
三亿文库包含各类专业文献、生活休闲娱乐、文学作品欣赏、专业论文、应用写作文书、高等教育、外语学习资料、98通用异步收发器(UART)等内容。 
 通用异步收发器UART设计_工学_高等教育_教育专区。通用异步收发器UART的设计。涉及编程,仿真,硬件测试通用异步收发器 UART 设计――现代电子系统设计 一、实验原理:...  18 武汉理工大学《FPGA 原理及应用》课程设计报告 摘要 UART(Universal Asynchronous Receiver Transmitter 通用异步收发器)是一 种应用广泛的短距离串行传输接口。常常...  1、UART 简介 UART(Universal Asynchronous Receiver Transmitter 通用异步收发器)是一种应用广泛 的短距离串行传输接口。常常用于短距离、低速、低成本的通讯中。8250...  通用UART_计算机硬件及网络_IT/计算机_专业资料。完成基本的异步收发 无校验位通用异步收发器(UART)设计一:简介 通用异步收发器(Universal Asynchronous Receiver Transm...  2.5 UART 设计总模块将发送器和接收器模块组装起来, 就能较容易地实现通用异步收发器总模块, 而且硬件 实现不需要很多资源,尤其能较灵活地嵌入到 FPGA/CPLD 的...  采用 Verilog HDL 语言作为硬件功能的描述,运用模块化设计方法分别设计了通用 异步收发器(UART)的发送模块、接收模块和波特率发生器,并结合现场可编程门阵列(FPGA) ...  基于FPGA的通用异步收发器设计_IT/计算机_专业资料。 基于 FPGA 的通用异步收发器设计作者: 学号: 指导教师 摘要:文章简要介绍了 UART 的基本功能,采用 Verilog HD...  图4 接收模块仿真波形图 图5 发送模块仿真波形图 3 通用异步收发器模块的设计分析 UART的设计采用层次结构化的设计方法,分别对各底层模块进行设计, 最 后将底层...  FPGA 通用异步收发器设计一.设计目的 1.了解短距离串行传输接口。 2.了解 FPGA...顶层模块 异步收发器的顶层模块由波特率发生器、UART 接收器和 UART 发送器构成...}

我要回帖

更多关于 usart和uart区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信