📄 f449串口通信编程练习-06-11-12.s43
字号:
#include "msp430x44x.h"
;********** 2006/11/13
;异步串行通信编程练习举例:编一个发送程序采用9600波特率将0--9数字发送出去,
;USART时钟采用1.048576MHZ,8位字符,不校验,串行异步方式通信,不检错,
;分别采用查询方式和中断方式进行发送
;
;
ORG 0200H
TXD_BUF DS 10 ;定义10个发送缓存区单元
TXDP DW 0 ;定义发送数据指针
RXD_BUF DS 10 ;定义10个接收缓存区单元
RXDP DW 0 ;定义接收数据指针
TXD_ST = 0BEH ;定义发送数据起始符
TXD_END = 0EDH ;定义发送数据结束符
LED = 04H ;LED接P4.2
;------------------------------------------------------------------------------
ORG 01100h ;程序代码起始地址 Program Start
;------------------------------------------------------------------------------
RESET mov.w #0A00h, SP ;建立堆栈指针 Initialize '449 stackpointer
mov.w #WDTPW+WDTHOLD, &WDTCTL ;关闭看门狗 Stop WDT
;波特率为9600时使用1.048576MHZ晶振时的串口控制寄存器设置
MOV.B #SHAR+SWRST, &UCTL0 ;字符长度8位,异步方式
mov.b #SSEL1, &UTCTL0 ; UCLK =SMCLK 使用子时钟时的串口控制寄存器设置
mov.b #00h, &UBR10 ;1048576Hz/9600=109.226 高8位为0
mov.b #6Dh, &UBR00 ;1048576Hz/9600=109.226 (109=6DH)低字节为6DH
mov.b #22H, &UMCTL0 ;或采用教材P213表3.17中的03
MOV.B #0, R5 ;向发送数据区预置待发送的数据0--9
MOV.B #9, R4 ;建立计数器
MOV #TXD_BUF, R6 ;建立发送数据指针
SET_N MOV.B R5, 0(R6)
INC R6 ;调整发送数据缓冲区指针
INC.B R5 ;修改发送数据
DEC.B R4 ;计数器减1
JNZ SET_N
MOV.B #TXD_END, 0(R6) ;在发送数据区的最后一个单元中填如结束符TXD_END=EDH
;ttttttt发送、接收控制位和发送、接收中断允许控制位见P401附录2中的ME1和IE1中
bis.b #UTXE0+URXE0, &ME1 ;打开发送器和接收器
bis.b #UTXIE0, &IE1 ;允许发送器中断
bis.b #URXIE0, &IE1 ;允许接收器中断
bis.b #030h, &P2SEL ;将P2.4,P2.5设置为串口通信特殊功能
bis.b #010h, &P2DIR ;将P2.4设置为输出
TTX BIT.B #UTXIFG0, &IFG1 ;测试发送器是否准备好
JZ TTX ;若未准备好则等待
MOV.B #UART_ST, &TXBUF0 ;在主程序中发送第1个数据(发起始代码F0H)
EINT ;打开CPU中断
Mainloop bis.b #LPM0,SR ; Enter LPM0 进入低工耗状态
jmp Mainloop ; Do nothing
;------------------------------------------------------------------------------
;可采用查询方式发送也可采用中断方式发送
;------------------------------------------------------------------------------
MOV #TXD_BUF, R6 ;建立发送数据指针
TX0 BIT.B #UTXIFG0, &IFG1 ;测试发送器是否准备好,发送器准备好标志在P401附录2中的IFG1中
JZ TX0 ;若未准备好则等待
MOV.B @R6+, &TXBUF0 ;若已准备好则将待发数据传送到发送器缓冲器即可发送出去
CMP.B #TXD_END, &TXBUF0 ;采用查询方式发送时在这里判断是否为发送结束码EDH
JNZ TX0 ;若采用中断方式发送时应在中断服务程序中判断是否为发送完
END
;******采用中断方式进行发送
;TXD_ST = 0BEH
;TXD_END = 0EDH
TXD_INT ;发送中断服务子程序
MOV.B @R6+, &TXBUF0 ;发送1个数据数据
MOV R4, &TXDP
CMP.B #TXD_END, &TXBUF0 ;判断是否为结束码FFH
JNZ TX_END
MOV #TXD_BUF, R6 ;发送数据指针复位
BIC.B #UTXIE0, &IE1 ;关闭发送中断
BIC.B #UTXE0, &ME1 ;关闭发送器
;BIS.B #URXE0, &ME1 ;打开接收器
;BIS.B #URXIE0, &IE1 ;允许接收中断
;MOV #RXD_BUF, &RXDP ;建立接收数据指针
TX_END
RETI
;------------------------------------------------------------------------------
; Interrupt Vectors Used MSP430x44x
;------------------------------------------------------------------------------
ORG 0FFFEh ;复位中断向量
DW RESET ;
ORG 0FFF0h ;发送中断向量
DW TXD_INT ;
ORG 0FFF2h ;接收中断向量
DW TXD_INT ;
ORG 0FFEEh ; ADC12 Interrupt Vector
DW AD12_INT ;
END
;SSSSSSSSSSSSSSSSS使用外接8MHZ晶振时的系统时钟模块初始化程序
SetupOSC bic.b #XT2OFF, &FLL_CTL1 ; Enable XT2 OSC
SetupOsc bic.b #XT2OF, &FLL_CTL0 ; Clear XT2 OSC fault flag
bit.b #XT2OF, &FLL_CTL0 ; XT2 OSC fault flag set?
jnz SetupOsc ; OSC Fault, clear flag again
bic.b #OFIFG, &IFG1 ; Safe, clear OSC fault flag
bis.b #SELM_XT2+SELS, &FLL_CTL1 ; MCLK = XT2 #SELM1
;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
MOV.B #SHAR+SWRST, &UCTL0 ;字符长度8位,异步方式
MOV.B #SSEL1, &UTCTL0 ;选择SMCLK作为时钟源
MOV #833, &RAM1 ; 8MHZ/9600=833.333
MOV.B &RAM1, &UBR00 ;将833转换成16进制数送波特率分频系数寄存器
MOV.B &RAM1+1, &UBR10
MOV.B #49H, &UMCTL0 ;01001001=49H波特率分频微调系数(即0.333X8=2.664取近似值3)
;即每个字节(8位)的分频系数中有3个分频系数要加1,这里取49H即为
;在发送每个字节的D6、D3、D0位时(应尽可能均匀分布)其波特率分
;频系数为834而其余5个系数用833,这样可减少波特率的累计误差
;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEND
ADC_WD ;MOV &ADC10MEM, R12 ;读出温度值送R12
CALL #Trans2TempC ;调用将温度转换为摄氏温度子程序
CALL #BIN2BCD5 ;调用将温度转换为BCD码子程序
MOV R13, &TEMP ;转存到温度存放单元
MOV.B &TEMP, &TX_DAT+1 ; &VOLT
BIS.B #0B0h, &P3SEL ;设置P3.4,P3.5为TXD和RXD,P3.7为ADC通道7
BIC #ENC, &ADC10CTL0 ;A/D模块设置前应先将ADC10CTL0中的转换使能位ENC置0!!
BIS.B #80H, &ADC10AE ;允许扭矩模拟信号从P3.7输入(ADC10AE_7)
MOV #INCH_7+ADC10DIV_4+ADC10SSEL_2+CONSEQ_0, &ADC10CTL1 ;扭矩输入为A7、ADC10CLK/8
MOV #SREF_5+ADC10SHT_3+ADC10SR+REFON+ADC10ON+ADC10IE, &ADC10CTL0 ;
;1.5V参考电压(+REF2_5V),允许中断,单通道单次转换时ADC10CTL0中的MSC应为0
ADC_END BIS #ENC+ADC10SC, &ADC10CTL0 ;重新启动采样与转换
POP R14
POP R5
RETI
;TTTTTTTTTTT温度变换子程序: Trans2TempC
;Subroutine coverts R12 = ADC10MEM/1024*423-274
;oC =((x/1024)*1500mV)-986mV)*1/3.55mV = x*423/1024 - 274 (应为277.75)
; =(1500X-1009664)/3635.2=1500X/3635.2-277.75=0.4126X-277.75
;Input: ADC10MEM 0000 - 0FFFh, R11, R12, R14, R15 working register
;Output: R12 0000 - 091h, 1500mV为A/D的参考电压
;-------------------------------------------------------------------
Trans2TempC mov.w &ADC10MEM, R12 ;
mov.w #423, R11 ; C
call #MPYU1 ;
bic.w #00FFh, R14 ; /1024
add.w R15, R14 ;
swpb R14 ;
rra.w R14 ;
rra.w R14 ;
;mov.w R14, R12 ;
sub.w #278, R14 ; #274, R12
ret ;
;--------------------------------------------------------------------
;++++++双字节(16位)二进制数转换成5位BCD码子程序(该算法使用十进制运算指令)
;入口参数:R14,出口参数:R14和R13,其中BCD码的最高位在R14的低4位
BIN2BCD5 ;MOV #0FFFFH, R14 ;测试指令 R12
MOV #16, R15 ;建立计数器
CLR R13 ;BCD码单元清0 R12
B1 RLA R14 ;二进制数左移1位,将移出位通过进位位
DADD R13, R13 ;加到十进制单元并进行十进制乘2计算
JNC B2
INC R14 ;BCD码高位(万位)加1 R14
B2 DEC R15 ;计数器减1
JNZ B1 ;若不为0则继续
RET ;
;-----部分积右移方式计算16位乘法,入口参数:被乘数为R11,乘数为R12,积的高16位为R15,低16位为R14
MPYU1 ;MOV #1234, R11 ;这两条指令调试时使用
;MOV R9, R12 ;
CLR R15 ;积清0
CLR R14
MOV.B #16, R10 ;建立计数器
CLRC
;MOV #05H, R12
M1 RRC R12 ;乘数右移1位
JNC RR1
ADD R11, R15
RR1 RRC R15
RRC R14
DEC.B R10
JNZ M1
RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -