如果没有开中断,则通过检测TI/RI是否为1来检测发送或者接收结束否,这两个标志位无论是中断法还是查询法都只能使用软件清零。
总结一下上面的图:即是表示要触发串口中断,首先要TI/RI其中有一个为1,其次串口中断ES要允许,紧接着总中断为EA要为1,满足这些条件就能触发串口中断,然后根据串口的中断优先级控制位PS到中断服务程序所在地址处执行程序。
利用TUSB3410 USB-TO-UART桥接芯片实现MSP430微控制器与USB设备通讯的一种接口方案
通过该USB接口可实现高达921 600bit/s的数据传输速率,也可通过该接口下载MSP430程序代码,是一种MSP430系列微控制器的高效USB接口解决方案
硬件设计
系统结构框图如图1所示,主机PC与MSP430之间可进行全双工串口通讯,主机PC经TUSB3410虚拟的一个COM口与MSP430的硬件USART模块进行通讯,本文重点叙述TUSB3410与MCU之间的软、硬件设计。
系统采用USB总线供电模式,MCU可通过I2C接口对TUSB3410进行在线编程及外部EEPROM存储器的配置。
1.TUSB3410接口芯片
TUSB3410为TI公司推出的一款用于USB-TO-UART端口的桥接器,包括通过USB总线与主机进行通信所必需的全部逻辑电路,符合USB2.0规范,支持最高12Mb/s的全速传输,支持USB中止、恢复及远程唤醒功能;同时,其内部包含一个8052的CPU核、16KB RAM、包含I2C引导加载程序的10KB ROM,4个通用I/0口,具有USB总线供电和自带电源两种供电模式。
TUSB3410引脚框图如图2所示:
2.USB配置
TUSB3410可以支持多种应用,本文所描述的参考设计配置如表1所示。
对于USB的兼容性来说,任意USB设备都具有唯一的VID(厂商识别码)和PID(产品识别码),VID/PID值作为一描述符传输给主机PC,并且与存储在驱动INF文件中的值相匹配, *** 作系统根据VlD/PID加载不同的驱动程序。
外部EEPROM用于存储配置参数,如VID/PID信息等,既可通过MCU经12C模块将EEPROM的镜像文件写入EEP-ROM,也可通过专用EEPROM编程器直接对EEPROM进行镜像文件写入TUSB3410也通过12C接口读取EEPROM数据。
3.硬件电路原理
系统原理图如图3所示,本文以MSP430F1612(U1)为例,任意一款内部含UART模块的MSP430微处理器均可与TUSB3410连接,MSP430F1612为MSP430系列中的高端MCU,丰富的资源使得开发具有更多的灵活性。
MSP430F1612选用8MHz晶振工作,MCU的6个引脚P1-P6通过PORT1-PORT6的8引脚插针引出,方便MCU与TUSB3410(U2)及外围器件的连接;SW1-SW4按键和LED1-LED4指示灯均通过I/O口控制,演示测试过程;同时,MCU与标准14针JTAG接口连接用于调试程序或调整电压值。
系统采用USB总线供电,同时LED5指示灯点亮,TUSB3410(U2)的USB数据信号经双路USB端口瞬态抵制器SN75240(U3)后连接到标准的USB B型连接口,以增强系统ESD抗干扰能力;USB总线提供的5V电压经TPS77301(U4)3.6V LDO稳压后作为MCU系统的VCC电压。
外部EEPROM(U5)通过12C通讯并存储USB配置参数,EEPROM的大小根据存储量选择,编程时通过短接JP1跳针与EEPROM的SCL信号线相连,同时TUSB3410通过USB将标准的VID/PID值传送到主机PC。
TUSB3410选用12MHz晶振,与MCU信号连接如表2所示,数据传输时,MCU的UART模块开始工作,支持TUSB3410所有波特率,同时通过12C模块与外部EEPROM采用在线编程方式直接存储数据MCU的P3.O/SETO引脚作为TUSB3410的复位脚,当MCU访问EEPROM时,复位该引脚,当没有外设连耐也可用该引脚进行复位测试。
4.低成本参考设计
系统的功耗设计可以从两方面考虑:(1)不使用外部EEP-ROM(2)不使用外部晶振。
(1)不使用外部EEPROM
利用TUSB3410实现的USB转UART接口可以不使用外部EEPROM,VID/PID描述符使用TI的默认缺省值,TUSB3410固件从主机PC上下载即可实现通讯,但是,存在两个问题:①因为不具备唯一VlD值,系统的USB设备兼容性不好;②当主机检测到两个不同USB设备,具有相同的VID/PID和序列号时,可能会导到USB设备不能正常工作或发生设备连接冲突所以,通常设计中不推荐采用此方法,除非该系统为独立总线工作方式,即不与外界任何USB设备同进与主机通讯。
(2)MSP430微控器器不使用外部晶振
TUSB3410由CLKOUT引脚输出UART波特率或一个固定的3.556MHz的频率信号,该频率信号可以作为MCU的外时钟输入,这种稳定的频率信号可作为MCU外设的工作频率,此时MCU无须连接外部晶振。
当系统选用TUSB3410产生的频率作为MCU时钟时,只需修改TUSB3410固件,通过设置MODECNFG配置寄存器的CLKOUTEN位,CLKOUT位使能输出,同时,CLKSLCT位用于选择以UART输出还是固定频率输出。
修改后的固件存放在外部EEPROM或存放于系统的驱动程序包中,当存于系统驱动程序包中时,设备连接时修改后的固件自动从 *** 作系统驱动程序中载入,MCU的OSCFAULT位用于检测是否系统使用外部晶振当TUSB3410输出7.3728MHz频率作为MCU的UART模块的时钟源时,此时UART传输速率可达921 000波特。
软件设计
MCU固件的主程序流程图如图4所示,MCU上电复位后调用InitSystem()初始化程序,初始化外设、看门狗、通用I/O口等,设置系统时钟为外部8MHz晶振,同时将USARTO设为12C模式与外部EEPROM实时通讯。
MCU初始化时,TUSB3410处于复位状态,MCU通过12C直接检测外部EEPROM的有效地址位和ACK应答位,当接收到有效ACK信号时,则调用EEPROM-Verify()程序校验该EEPROM中的程序是否与MSP430F1612内部Flash存储的EEPROM镜像文件一致若检测到外部EEPROM为空,则调用EEPROM_Write()程序将MSP430F1612内部Flash存储的EEPROM镜像写入EEPROM当EEPROM程序更新后,TUSB3410释放复位信号,读取外部EEPROM值,当连接到USB主机控制器时,TUSB3410会将这些数据提供给USB主机核对,同时将MCU复位引脚设为NMI模式,防止MCU意外复位。
初始化后,MCU通过Timer_B7模块检测SWl-SW4按键状态,当有键按下,捕获/比较模块捕捉到按键的上升沿信号时产生中断,同时唤醒MCLJ。
中断服务程序流程图如图5所示,首先将USARTO设为UART异步串口模式,然后以460 800波特进行通讯,一帧数据通信的字符格式为8位数据位和1个停止位,没有奇偶校验位当系统要求高速率传输时,主机PC需打开虚拟COM口,并MCU配置相匹配,此时MCU传输速率可达到921 600波特。
中断方式下进行串口通讯的正确方法一般普遍的把串口通讯分为查询方式和中断方式。查询方式比较容易理解,各种书籍上都介绍的比较清楚。但中断方式,没有几本书讲得好的,甚至有些例程根本无法实际应用。
问题有:
1,半中断法。只使用接收中断,不使用发送中断,发送时还是依靠查询中断标志的办法;如下: ES = 0//若是接收使用中断方式,某些单片机需要关中断。但C51不一定需要。这里只是示例。 SBUF = needsendcharWhile (!TI)TI = 0ES = 1 这里的问题是:发送数据时需要等待数据发完才能继续其他工作,程序效率降低;发送时需要关中断,影响数据接收。
2,接收中断的处理方法错误。如下: 中断程序: void ser() interrupt 4 { RI = 0 temp = SBUF//读走数据,放入缓存(全局的)变量 rx_flag = 1//设置接收标志 } 主程序: void main(){ „//初始化 While (1) {If (rx_flag ==1){//查询接收标志 rx_flag = 0//清楚接收标志 x = temp//从暂存变量读取数据 „//接收处理 }„//其它 *** 作 } } 这里的问题是:如果串口接收数据的间隔时间小于“接收处理”和“其它 *** 作”所用的时间时,接收数据会丢失一部分。 正确使用中断方式处理串口收发应达到以下目的: 1,完全使用中断控制接收和发送,以达到最快的收发速度。 2,接收和发送互不影响,达到全双工通讯效果。
3,应用程序不发生等待,以达到最高运行效率。
undefined
正确的中断发送方法如下:
1,建立一个足够大小的环形发送缓冲区,建立一个信号量(用于指示发送的数据量),建立一个发送标志位(用于指示发送状态)。
2,应用程序将数据写入环形发送缓冲区,查询发送接收标志,若不在发送状态,手动触发中断。
3,产生发送中断时,查询信号量,以判别发送缓冲区内是否有数据;若有,置发送标志位,从缓冲区读取数据发送,累减信号量;若无,清除发送标志位。 C51的例程如下:
//变量定义 #define BUF_SIZE 0x10//环形收发缓冲区长度 //发送参数 char tx_circbuf[BUF_SIZE]//环形发送缓冲区 uint8 tx_sem//信号量 bool tx_run//发送标志位 uint8 tx_circin//进环形缓冲区的位置指示 uint8 tx_circout//出环形缓冲区的位置指示 //发送初始化程序 void tx_init(void){ //硬件初始化 略 //发送参数初始化 tx_sem = 0 tx_run = Falsetx_circin = 0tx_circout = 0} //中断程序 void tx_int(void) interrupt 4 { if (TI){ TI = 0 if (tx_sem){SBUF = tx_circbuf [tx_circout]// 发送缓冲区中的字符 if (++tx_circout >= BUF_SIZE) tx_circout = 0 tx_sem--//累减信号量tx_run = True//置发送标志位 } else tx_run = False//清除发送标志位 } } //发送处理程序,由应用程序调用 //输入:发送数据指针,发送数据长度
void tx_data(char * txbuf,uint8 len){ while (len){ tx_circbuf [tx_circin] = *txbuf++// 存入数据到发送缓冲区 if (++tx_circin >= BUF_SIZE) tx_circin = 0tx_sem++//累减信号量 len-- if (tx_run == False)TI=1//查询发送状态标志。若发送空闲,触发中断,发送数据的工作由中断程序自动完成。 } }正确的中断接收方法如下:
1,建立一个足够大小的环形接收缓冲区,建立一个信号量(用于指示接收的数据量)。
2,发生接收中断时,读出字节放入接收缓冲区,并累加信号量。
3,应用程序查询接收标志,如信号量不为0,则从接收缓冲区读取数据进行处理,累减信号量。 C51的例程如下: //变量定义 #define BUF_SIZE 0x10//环形收发缓冲区长度 //接收参数 char rx_circbuf[BUF_SIZE]// 环形接收缓冲区 uint8 rx_sem// 信号量 uint8 rx_circin//进环形缓冲区的位置指示 uint8 rx_circout//出环形缓冲区的位置指示 //接收初始化程序 void rx_init(void){ //硬件初始化 略 //接收参数初始化 rx_sem = 0rx_circin = 0rx_circout = 0} //中断程序 void rx_int(void) interrupt 4 { if (RI){ RI = 0 rx_circbuf [rx_circin] = SBUF// 读出字节放入接收缓冲区 if (++rx_circin >= BUF_SIZE) rx_circin = 0rx_sem++//累加信号量
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)