CCS和proteus联动仿真msp430控制四位数码管显示数字

2022-07-26,,,,

文章目录

  • 前言
  • 一、软件基础
  • 二、CCS生成需要的hex文件
    • 1.建立工程和设置
    • 2.写代码
  • 三、proteus搭建电路与载入hex
  • 总结

前言

又是一年电子信息杯,每年单片机都有很多人放弃,我那时在环境搭建上耗了很多时间
这里分享一个我很早写的一个数码管显示的代码和整体流程,希望能对后来人有所帮助

一、软件基础

proteus和CCS(我用的是CCS9.3.0和proteus8.6)
下载和安装破解只要在CSDN上搜索就行,这里给出两个链接,如果你按流程安装有问题欢迎评论区指出
CCS
proteus

二、CCS生成需要的hex文件

1.建立工程和设置

file→new→CCS project 设置如下,选中芯片msp430g2553,创建工程名字(segdisplay),点击finish

正常建立以后点开main.c文件如下图所示

选中工程,右键,左键单击properties,左键单击Build界面如下所示

点击Steps,如下图所示
直接在Post-build steps中输入

C

G

T

O

O

L

H

E

X

"

i

"

{CG_TOOL_HEX}" -i "

CGTOOLHEX"i"{BuildArtifactFileName}” -o “${BuildArtifactFileBaseName}.hex” -order MS -romwidth 16

在Description中输入

Create flash image: Intel-HEX

点击 左侧build下的MSP430 Hex Utility,勾选Enable MSP430 Hex Utility,如下图所示

点击apply and close。

2.写代码

代码如下(示例):

/* *************************************************************
 * 电子信息杯初赛代码
 *创建date  2019_12_03
 * by hwk HeWenKang@bupt.edu.cn
*********************************************************** */
/* *************************************************************
写于2020_12_11
回看这些代码真是黑历史-=也不知道这个代码能不能正常运行,如果不行多看看引脚定义有没有问题
建议早点看中断内容,脱离轮询的笨办法;在src里面多创建一些文件,按功能分类放;多些注释,养成良好习惯;多用define,增强代码的可移植性;函数命名多用下划线和英文
测频率和占空比可以用定时器捕获,但是proteus仿真有点问题,管脚和代码里对应不上,可能存在进不去中断的情况
单片机路漫漫其修远兮,加油冲冲冲
*********************************************************** */
#include <msp430g2553.h>

/* *************************************************************
 *   1ms延时函数
  *     延时函数,具体延时的值根据主时钟频率改变而改变,调节内部i大小即可
 * by hwk HeWenKang@bupt.edu.cn
*********************************************************** */
void delay_1ms(void)
    {
        unsigned int i;
        for (i = 0; i<40; i++)
        ;
    }

/*******************************************************************
 * nms延时函数
  *     延时函数,具体延时的值根据主时钟频率改变而改变
 * by hwk HeWenKang@bupt.edu.cn
 *******************************************************************/
void delay_nms(unsigned int k)
    {
        unsigned int i = 0;
        for (i = 0; i <k ; i++)
            delay_1ms();
    }

/*******************************************************************
  * 引脚初始化函数
  *  设置引脚输入输出
 * by hwk HeWenKang@bupt.edu.cn
 *******************************************************************/
void GPIO_Init(void)
    {
    P1OUT = 0;//P1初始值为0x00;
    P1DIR|=BIT1+BIT2+BIT3+BIT4+BIT5; // P1.1、p1.2、P1.3、P1.4设为输出(置1)
    P1DIR&=~BIT7;
    P2OUT = 0;//P2初始值为0x00;
    P2DIR|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT6+BIT7; // P2设为输出(置1)
    }

/* ******************************************************************
 *   7位数码管数字输出辅助函数
 *  m==3处是小数点,所以比较特殊,原理就是扫频,m是第几位,n是该位数字
 * by hwk HeWenKang@bupt.edu.cn
 *********************************************************************/
void segprintf(unsigned int m,unsigned int n){

       P1OUT=0;
       if(m==1)
       {P1OUT = BIT1;P2OUT =0XFF;
       }
       else if(m==2)
       {P1OUT = BIT2;P2OUT =0XFF;
       }

        else if(m==3)
         { P1OUT = BIT3;P2OUT =0XFF;
         }
         else if(m==4)
         {P1OUT = BIT5;P2OUT =0XFF;
        }
         else
           P1OUT=0;
       if(m==3)
       {  switch(n){
         case 0: P2OUT=BIT1;break;
         case 1: P2OUT=BIT1+BIT2+BIT3+BIT4+BIT7;break;
         case 2: P2OUT=BIT2+BIT5;break;
         case 3: P2OUT=BIT2+BIT3;break;
         case 4: P2OUT=BIT3+BIT4+BIT7;break;
         case 5: P2OUT=BIT3+BIT6;break;
         case 6: P2OUT=BIT6;break;
         case 7: P2OUT=BIT1+BIT2+BIT3+BIT4;break;
         case 8: P2OUT =0;;break;
         case 9: P2OUT=BIT3;break;
         }}
       else
       {
         switch(n){
         case 0: P2OUT=BIT0+BIT1;break;
         case 1: P2OUT=BIT0+BIT1+BIT2+BIT3+BIT4+BIT7;break;
         case 2: P2OUT=BIT0+BIT2+BIT5;break;
         case 3: P2OUT=BIT0+BIT2+BIT3;break;
         case 4: P2OUT=BIT0+BIT3+BIT4+BIT7;break;
         case 5: P2OUT=BIT0+BIT3+BIT6;break;
         case 6: P2OUT=BIT0+BIT6;break;
         case 7: P2OUT=BIT0+BIT1+BIT2+BIT3+BIT4;break;
         case 8: P2OUT =BIT0 ;break;
         case 9: P2OUT=BIT0+BIT3;break;
         }
       }
 delay_nms(1);
// P1OUT=0;
// P2OUT=0;
}

/* ******************************************************************
 *   频率输出函数
 *  待补充
 * by hwk HeWenKang@bupt.edu.cn
 *********************************************************************/
int  frequency(void)
    {
     return(1314);
    }

/* ******************************************************************
 *    占空比输出函数
 *  待补充
* by hwk HeWenKang@bupt.edu.cn
 *********************************************************************/
int  dutycycle(void)
    {
      return (1413);
    }

/* ******************************************************************
 *  7位数码管数字输出函数
 * 输入4位数k,函数取每一位的数,通过函数segprintf(a,b)将每一位在对应位输出
 * by hwk HeWenKang@bupt.edu.cn
 *********************************************************************/
void printfseg(unsigned int k)
{
    unsigned int a;
    unsigned int b;
    b=k/1000;
    a=4;
    segprintf(a,b);
    k=k-1000*b;
    b=k/100;
    a=3;
    segprintf(a,b);
    k=k-100*b;
    b=k/10;
    a=2;
    segprintf(a,b);
    k=k-10*b;
    b=k;
    a=1;
    segprintf(a,b);
}

/* ******************************************************************
 *  主函数
 *尽量把函数写在外面,最好写在别的文件里面然后include,main函数越简单越好
 * by hwk HeWenKang@bupt.edu.cn
 *********************************************************************/
int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;// 关闭看门狗,我也不知道为什么,但基本上都有这个代码,好像是为了防止程序跑飞
//             BCSCTL1 = CALBC1_1MHZ;
//            DCOCTL = CALDCO_1MHZ;
//            BCSCTL2 = SELM_0 | DIVM_0 | DIVS_3;
        GPIO_Init();
        //定义引脚功能
        unsigned int f=0;
        unsigned int z=0;
        f=frequency();
        z=dutycycle();

        while(1)               //用中断可以节省资源,但是不太会,用轮询方式消耗资源达到效果,反正他不看源代码:(
            {
              while(1)                        //循环A
                {
                    if((P1IN & BIT7) == BIT7)
                       printfseg(f);
                    else
                       {
                           while(1)
                              {
                                  if((P1IN & BIT7) == BIT7)
                                    break;
                                  else
                                         ;
                              }
                           break;
                       }
                }
              while(1)                             //循环B
                  {
                    if((P1IN & BIT7) == BIT7)
                        printfseg(z);
                    else
                        {
                          while(1)
                             {
                              if((P1IN & BIT7) == BIT7)
                                break;
                              else
                                     ;
                             }
                          break;
                        }
                  }
             }        //最大while的后括号
    }


完成以后点击左侧小锤子build 工程,build finish以后显示如下


三、proteus搭建电路与载入hex

这部分比较简单,照着图片找元件搭就行,搭建出来的电路效果如下图所示,我的主页里也给出这个电路的工程文件proteus_seg。

右键芯片,选择编辑元件,选择program file,找到之前在CCS中工程目录debug目录下的.hex文件

打开,确定,然后点左下角运行

总结

代码里面当时测试有一个bug,发现当输入的数字是0开头时,数码管显示会显示不一样的数,就是说如果return的z是0520,显示的就是0336,如果是520,显示的就是0520,这点要注意一下。
然后代码显示是保留2位小数的显示,具体逻辑可以看源代码,注释还行,应该看得懂。

后面还会遇到proteus仿真问题,比如说定时器捕获中断进不去,串口没有输出,这些在烧录硬件时都不会遇到,但是烧录硬件也有它的问题,测试起来没有仿真方便。

最后附上我去年电子信息杯在B站的两个视频,还有很多腾讯视频的视频我就不发了,你们去腾讯视频搜电子信息杯应该就能搜到我们那一级的黑历史。
利用IAR生成.hex文件并在Proteus中运行
2020F134_msp430演示视频_电子信息杯

再强调一下我在代码前面写的一段话
建议早点看中断内容,脱离轮询的笨办法;在src里面多创建一些文件,按功能分类放;多些注释,养成良好习惯;多用define,增强代码的可移植性;函数命名多用下划线和英文
测频率和占空比可以用定时器捕获,但是proteus仿真有点问题,管脚和代码里对应不上,可能存在进不去中断的情况
单片机路漫漫其修远兮,加油冲冲冲

本文地址:https://blog.csdn.net/weixin_43812576/article/details/111087056

《CCS和proteus联动仿真msp430控制四位数码管显示数字.doc》

下载本文的Word格式文档,以方便收藏与打印。