设为首页 收藏本站
查看: 1486|回复: 0

[经验分享] MSP430FG439上实现IO模拟UART以及移植要点解析

[复制链接]

尚未签到

发表于 2015-11-5 13:29:34 | 显示全部楼层 |阅读模式
本文来自http://blog.iyunv.com/hellogv/ ,引用必须注明出处!     

        最近要做MSP430上的开发,一上手就要做IO模拟UART这种难度的玩意,幸好网上已经有很多现成的MSP430的软串口实现例子,本文代码大部分参考>http://www.microcontrol.cn/430base.htm上的《MSP430的Timer_A实现模拟串口功能例程》,并且成功移植到MSP430FG439之上,不过移植的过程有点匪夷所思。。。。由于才学430没几天,所以花了一周才调试出IO模拟UART。。。。
  

  接下来就贴上100%能在MSP430FG439上使用的代码(即使是同一Family的不同型号,也会有区别):
  //利用定时器A 作串行口波特率发生器用,利用捕捉比较功能实现异步串行通信。 //芯片型号:MSP430FG439           P1.0---TXD   P1.1---RXD//Timer_A TACLK=ACLK //波特率为 2400BIT/S TBIT1=14 TBIT0_5=6//帧格式:(0)XXXXXXXX(1),0为起始位,1为结束位,XXXXXXXXX为8位数据#include  <msp430xG43x.h>#define TBIT1 14;                      //TBIT1 为1 位时间 #define TBIT0_5 6;                    //TBIT0_5 为半位时间 #define TXD BIT0                      //使用P1.0作为发送,特殊功能脚,用CCI0A做比较输出#define RXD BIT1                      //使用P1.1作为接收,特殊功能脚,用CCI0B做捕获输入unsigned int TR_COUNT;                 //发收计数器 unsigned int T_DATA=0x00;              //发送缓冲器 unsigned int R_DATA=0x00;             //接收缓冲器 void init(void);                      //初始化 void txd (unsigned char byte);        //发送一字节数据 void rxd(void);                       //接收准备子程序 // ******************************************************// 主函数// *****************************************************main() { init();txd(0XFF);//由于发的第一帧会有错,所以先发送无用帧for(int i=0;i<255;i++)//发送0~255的数据txd(i);while(1){rxd();                                 //准备接收 LPM3;                               //进入休眠状态,收到数据后在唤醒txd(R_DATA);                 //把收到的数据重发}} // ******************************************************// 初始化函数// *****************************************************void init(void)                         { WDTCTL=WDTPW+WDTHOLD;                  //停止WDT P1DIR |= TXD;                                                 //TXD管脚为输出P1SEL |= (RXD+TXD);                                    //RXD和TXD都为特殊功能脚CCTL0|=OUT;                                                  //CCR0    OUT 设1 TACTL|=TASSEL_1+MC_2;                          //设定时器A 时钟源ACLK,设定时器为连续模式 _EINT();                                                            //开中断允许 } //******************************************************//发送一字节数据子程序 //输入参量:unsigned char 类型字节 // *****************************************************void txd(unsigned char byte) {   T_DATA=255-byte;           //关键点之一:这里与其它MSP430的软串口例程不同CCR0=TAR;                        //将TAR 时间存入CCR0,确定第一位 长度。 CCR0=CCR0+TBIT1;         //将每1 位时间周期加入CCR0。 //uart帧格式:(0)xxxxxxxx(1)T_DATA=T_DATA<<1;         //左移一位T_DATA|=BIT0;                      //最后一位为1TR_COUNT=10;                     //发送计数器。 CCTL0=OUTMOD0+CCIE+OUTMOD2;              //重新设置CCTL0(CCIS1-0=00) //捕获/比较模块输出模式1,充许模块中断。 while(CCIE&CCTL0);               //等待CCIE 是否为0?为0 则表示发送完数据。 } // *****************************************************//接收准备子程序 //依赖TA0 中断来接收一字节数据。 // *****************************************************void rxd(void) {TR_COUNT=8;                             //接收数据位 位数 //关键点之一:其它MSP430的软串口都是用下降沿(CM1),实践中我发现接收的问题就出在这里,所以我用CM0上升沿CCTL0 = SCS + CCIS0 + OUTMOD0 + CM0 + CAP + CCIE;  // 比较捕获为输出模式+比较捕获模块为中断允许+"上升沿捕获"+设置为捕获模式 //+选择CCI0B 为捕获源+同步捕获 } //******************************************************************************* #pragma vector=TIMERA0_VECTOR       //TIMER_A 中断函数 __interrupt void cc10int(void) { CCR0=CCR0+TBIT1;                   //重装下一位时间(当前时间+1 位时间) //---------------------------接收处理程序段 if(CCTL0 & CCIS0)                    //是处于接收中还是发送中? {if(CCTL0&CAP)                   //是捕获模式还是比较模式? {         CCTL0&=~CAP;                //是-开始捕获,将捕获功能改为比较功能 CCR0=CCR0+TBIT0_5;           //开始捕获位再加半位时间 }else {R_DATA=R_DATA>>1;            //处于比较功能,将前面 那位向低位移.if(CCTL0&SCCI)                       //这句等效于(P1IN&RXD)==1,如果RXD管脚是高电平{R_DATA|=BIT7;                   //则R_DATA的最高位置1}TR_COUNT--;                 //计数器减1if(TR_COUNT==0)              //是否接收完8 位? { R_DATA=255-R_DATA;      //关键点之一,这里也要用255减一次//*****************************CCTL0&=~CCIE;           //是接收完,捕获/ 比较块停止中断充许 LPM3_EXIT;             //退出低功率模式(一般,在进入LPM3 时才使用) } } }                              //接收结束 //---------------------------------------------------------------- else                                //开始发送程序段 { if(TR_COUNT==0) CCTL0&=~CCIE;                //关捕获/比较块中断,发送结束. else {if(T_DATA&0x0001)           //状态寄存器C 位是1,还是0? CCTL0&=~OUTMOD2;         //状态寄存器C 位为0,发送0.else CCTL0|=OUTMOD2;           //状态寄存器C 位为1,发送1.T_DATA=T_DATA>>1;             //将字节数据向右移一位 --TR_COUNT;                 //位计数器减1. } }}
  由于网上的MSP430例程都几乎一致(都是出自TI的例程),并且大体思路没有错误(不同型号之间的设置会有变化),所以接下来介绍一下初学者移植时也许遇到的问题:
  1.这里用了有特殊功能的IO脚,所以一定要对照芯片资料来确定自己所用的430对应功能在哪个IO上;
  2.重点:要清楚串口帧的格式,这里用到的是10位:(0)XXXXXXXX(1),0开头,1结尾。
  很多移植上的问题都是由此引起:
  (1)由于发送时,从低位开始,即从1先开始发送,0最后发送,所以XXXXXXX要掉转一次(T_DATA=255-byte;);
  (2)由于未知其他寄存器对TXD的影响,发送首帧时也许会出错,所以真正判断是否发送成功要从第二针开始(txd(0XFF););
  (3)接收的时候,也容易受到帧格式的影响。。。。网上的例程都是用下降沿(CM1),但RXD脚收到帧的第一位却是1,最后一位是0(正如前面所说的低位先发),所以改为CM0上升沿就可以收到了,收到的次序是1XXXXXXX0,XXXXXXX也要掉转一次(R_DATA=255-R_DATA;)才能还原源数据。
             版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-135459-1-1.html 上篇帖子: 是你证明CCIE,还是CCIE证明你? 下篇帖子: MSP430 入门学习资料
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表