嵌入式系统课程设计报告样例

《嵌入式系统应用》课程设计报告

        设计课题:基于STM32的直流电机调速

专业班级:   11电气1   

学生姓名:    朱帅      

指导教师:     蔡海滨       

设计时间:  20##--20151学期

工程技术学院

直流电机控制程序设计

摘要STM32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM Cortex-M3内核。本次使用的是STM32F103“增强型”系列。增强型系列时钟频率达到72MHz,从闪存执行代码,STM32功耗36mA,是32位市场上功耗最低的产品,相当于0.5mA/MHz。工作原理:是通过改变输出方波的占空比使负载上的平均电流功率从0-100%变化,从而改变直流减速电机速度。利用脉宽调制(PWM)方式,实现调速,它的优点是电源的能量功率,能得到充分利用,电路的效率高。

关键字:占空比   PWM输出  控制  STM32   电机  人机交互

设计概述及基本要求

用单片机编程实现直流电机的控制过程,要求:具有电压调速

第一章    系统概述

1.1 总框图设计

根据设计要求,我们把设计主要分为两个模块:显示模块,直流电机调速模块。

其原理图如下:

系统简介:

打开电源之后,电源指示灯亮,屏幕显示电机的控制电压,单片机根据采集的电压值进行PID调节,使电机的电压稳定在设定的值(电机的转速和电压成正比)

第二章  单元电路设计与分析

显示部分:

//写寄存器函数

void LCD_WR_REG(u8 data)

{

          LCD_RS_CLR;//写地址 

         LCD_CS_CLR;

          DATAOUT(data);

          LCD_WR_CLR;

          LCD_WR_SET;

         LCD_CS_SET;  

}

#else//正常IO

//写寄存器函数

void LCD_WR_REG(u8 data)

{

          LCD_RS=0;//写地址 

         LCD_CS=0;

          DATAOUT(data);

          LCD_WR=0;

          LCD_WR=1;

         LCD_CS=1;  

}

void LED_Init(void)

{

         RCC->APB2ENR|=1<<2;    //使能PORTA时钟         

         RCC->APB2ENR|=1<<5;    //使能PORTD时钟         

         GPIOA->CRH&=0XFFFFFFF0;

         GPIOA->CRH|=0X00000003;//PA8 推挽输出       

    GPIOA->ODR|=1<<8;      //PA8 输出高

                                                                              

         GPIOD->CRL&=0XFFFFF0FF;

         GPIOD->CRL|=0X00000300;//PD.2推挽输出

         GPIOD->ODR|=1<<2;      //PD.2输出高

}

PWM输出部分:

相关代码:

void PWM_Init(u16 arr,u16 psc)

{                                              

         RCC->APB1ENR|=1<<1;       //TIM3时钟使能     

         GPIOA->CRL&=0X0FFFFFFF;//PA7输出

         GPIOA->CRL|=0XB0000000;//复用功能输出   

         GPIOA->ODR|=1<<7;//PA7上拉     

         TIM3->ARR=arr;//设定计数器自动重装值

         TIM3->PSC=psc;//预分频器不分频

         TIM3->CCMR1|=7<<12;  //CH2 PWM2模式        

         TIM3->CCMR1|=1<<11; //CH2预装载使能       

         TIM3->CCER|=1<<4;   //OC2 输出使能   

         TIM3->CR1=0x8000;   //ARPE使能

         TIM3->CR1|=0x01;    //使能定时器3                                                                    

}

第三章     主体代码

/* 沉木冰悟 */

#include "stm8s_hard.h"

float det;                                         //误差参数、采样参数

u16 kk=0;

u16 pid_sum=0;

u16 pid_i_sum=0;

/************************************************************************

* Function Name  : PI算法函数

* Description     : PI算法

* Input          : Pi_temp实测参数,PID_NUM控制参数

* Output         : None

* Return         : None

************************************************************************/

u16 PI_MATH(float Pi_temp,u16 PID_NUM,u16 PID_max)

{

       det=0;

       det=1-Pi_temp/Pi;

       if (det>0.01||det<-0.01)                                //超出误差范围,进行调整

            {           

               pid_i_sum=pid_i_sum+det*pid_i;       //求出i的离散积分

               kk=(int)(det*pid_p);

               pid_sum=kk+(int)pid_i_sum;

               if ((PID_NUM+pid_sum)<0)                     //最小为0,否则为负数                                         PID_NUM=0;

               else

                    PID_NUM=PID_NUM+pid_sum;

               if (PID_NUM>PID_max)

PID_NUM=PID_max;                  //占空比最大不能超过95%

              }

       return(PID_NUM);

主函数部分:

int main(void)

{

       /*各模块初始化*/

。。。。。。。。。。。。。

       //显示提示信息1

。。。。。。。。。。。。。   

       //显示提示信息2

。。。。。。。。。。。。                 

while(1)

       {    

              adcx=Get_Adc(ADC_Channel_0);

              LCD_ShowNum(156,130,adcx,4,16);   //显示ADC的VAL值

              PI();                     //PI调节输出的PWM脉宽

              LCD_ShowNum(156,170,PWM_NUM,4,16);     //显示输出的PWM值

              temp=(float)adcx*(3.3/4096);

              adcx=temp;

              LCD_ShowNum(156,150,adcx,1,16);//显示电压值1

              temp-=adcx;

              temp*=1000;

              LCD_ShowNum(172,150,temp,3,16);//显示电压值2

       }

 }

第四章   结束语

本设计特点、存在的问题及改进意见:

在进行本设计时,充分利用mini开发板已有资源,对按键等硬件进行复用,极大地发回来已有器件的功用.

参考文献

[1]黄智伟.ARM9嵌入式系统设计基础教程[M].北京:北京航空航天大学出版 , 2006

[2]庄海军.基于S3C2410的IIS音频总线研究及其驱动实现[M].淮安教出版社,    2008

附件:     

元器件明细表

 

第二篇:嵌入式系统课程设计实验报告

嵌入式系统课程设计必做部分

学院:电控学院

专业:通信工程

 

设计名称:IIC同步串行通讯

1、设计的目的:

1.掌握S3C44B0IIC控制器的编程方法

2.编程实现串行EEPROM存储器24C16的数据存储和访问。

2、设计的内容:

1.学习S3C44B0 IIC控制器的原理与编程方法;

2.学习IIC存储器24C16的编程方法;

3.理解IIC存储器24C16的与S3C44B0的电路连接原理;

4.掌握C语言中断程序设计方法;

5.编程实现对24C16的数据存储和访问。

3、设计思路、遇到的问题及解决方法:

此次试验,我们结合《嵌入式系统原理及应用》教材以及老师提供的各种pdf和word资料,了解到了各种寄存器的配置方法,如IICDS等。对于例程中的各种函数,如Wr24C16(), Rd24C16(),__irq IicInt()等,通过对程序的仔细研读,最终了解了它们的各自用途,并在此基础上,编写了主函数。实现了从0-255共256个字节的写入及读取操作。

这次实验我们遇到了不少的难题,像开始使用ARM-Project Manager平台一开始,由于对此平台的不了解,我们走了许都弯路。像对于头文件的配置问题,总是配置不对,后来发现头文件为程序自主生成,无需配置。还有关于程序中的一些.s文件,开始并不知道是有何作用,后来在老师的指点下,发现有必要将其加入到sourse文件栏中调用,同时调用的同时,由于不理解调用的路径问题,多次编译失败,后来发现了问题,是路径配置不当,最终更改了路径,解决了问题。

再有,在对老师提供的例程进行阅读时候,发现了不少的啰嗦以及错误语句,例如Uart_Printf("%d\n",k);语句就不应该为Uart_Printf("%d\n",&k);这些问题我们都通过调试最终给予了改正。

4、设计的结果及验证

正确输出结果如下截图,从超级终端中回显显示了正确数据,实验成立。

流程图: 可选过程: 开始5、程序流程图如下:

   

 

 


6、全部源代码如下(可验证)

#include <string.h>

#include "C:\ARM251\44b0\44b.h"

#include "C:\ARM251\44b0\44blib.h"

#include "C:\ARM251\44b0\Def.h"

#include "C:\ARM251\44b0\iic.h"

#include "C:\ARM251\44b0\Option.h"

#include <stdarg.h>

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <ctype.h>

#define WRDATA      (1)

#define POLLACK     (2)

#define RDDATA      (3)

#define SETRDADDR   (4)

#define IICBUFSIZE 0x20

U8 _iicData[IICBUFSIZE];

volatile int _iicDataCount;

volatile int _iicStatus;

volatile int _iicMode;

int _iicPt;

void __irq IicInt(void);

void Wr24C16(U32 slvAddr,U32 addr,U8 data)

{

    _iicMode=WRDATA;

    _iicPt=0;

    _iicData[0]=(U8)addr;

    _iicData[1]=data;

    _iicDataCount=2;

    rIICDS=slvAddr;//0xa0 ,写 移位寄存器

    rIICSTAT=0xf0; //MasTx,Start

    //Clearing the pending bit isn't needed because the pending bit has been cleared.

    while(_iicDataCount!=-1);//中断完成,总线不忙,可以传送,同时移位寄存器已经准备好两个数据量

    _iicMode=POLLACK;

    while(1)

    {

    rIICDS=slvAddr;    // 0xa0 ,写 移位寄存器

    _iicStatus=0x100;    

    rIICSTAT=0xf0; //MasTx,Start

    rIICCON=0xaf;  //resumes IIC operation.IIC-BUS控制寄存器

    while(_iicStatus==0x100);   //rIICSTAT数值发给iicStatus,0xf0

    if(!(_iicStatus&0x1))    // Last-received bit is 0 (ACK was received),判断ack是否收到数据

        break; // when ACK is received

    }

    rIICSTAT=0xd0;  //stop MasTx condition   IIC-bus不忙

    rIICCON=0xaf;   //resumes IIC operation.

    Delay(1);       //wait until stop condtion is in effect.

    //write is completed.

}

void Rd24C16(U32 slvAddr,U32 addr,U8 *data)

{

    _iicMode=SETRDADDR;     //写模式开启

    _iicPt=0;               //data【】的计数器

    _iicData[0]=(U8)addr;    //取地址

    _iicDataCount=1;

    rIICDS=slvAddr;         //移位寄存器地址联系

    rIICSTAT=0xf0; //MasTx,Start  ,总线忙

    //Clearing the pending bit isn't needed because the pending bit has been cleared.

    while(_iicDataCount!=-1);

    _iicMode=RDDATA;

    _iicPt=0;  //数组数据变量

    _iicDataCount=1;   //?

    rIICDS=slvAddr;      //设置移位寄存器输出地点

    rIICSTAT=0xb0; //MasRx,Start       IIC-bus不忙

    rIICCON=0xaf;  //resumes IIC operation.  总线控制

    while(_iicDataCount!=-1);

    *data=_iicData[1];

}

void __irq IicInt(void)        //中断挂起

{

    U32 iicSt,i;          //?

    rI_ISPC=BIT_IIC;      //?

    iicSt=rIICSTAT;       //写入fo,d0,

    if(iicSt&0x8){} // when bus arbitration is failed. IIC-bus仲裁过程状态标志位

    if(iicSt&0x4){} // when a slave address is matched with IICADD   IIC-bus从地址状态标志位

    if(iicSt&0x2){} // when a slave address is 0000000b   IIC-bus 地址为0状态标志:

    if(iicSt&0x1){} // when ACK isn't received   IIC-bus上一次接收到的状态标志位

    switch(_iicMode)

    {

    case POLLACK:

        _iicStatus=iicSt;

        break;

    case RDDATA:

        if((_iicDataCount--)==0)

        {

        _iicData[_iicPt++]=rIICDS;

        rIICSTAT=0x90;  //stop MasRx condition , Master receive mode  IIC-bus不忙,Enable Rx/Tx

        rIICCON=0xaf;   //resumes IIC operation.

        Delay(1);   //wait until stop condtion is in effect.

                //too long time...

        //The pending bit will not be set after issuing stop condition.

        break;   

        }       

        _iicData[_iicPt++]=rIICDS;  //0,1

                //The last data has to be read with no ack.设置应答位,读取时为NO应答位

        if((_iicDataCount)==0)

        rIICCON=0x2f;   //resumes IIC operation with NOACK. 

        else

        rIICCON=0xaf;   //resumes IIC operation with ACK

        break;

    case WRDATA:

        if((_iicDataCount--)==0) //2 ,1,0,-1

        {

        rIICSTAT=0xd0;  //stop MasTx condition  IIC-bus不忙

        rIICCON=0xaf;   //resumes IIC operation.总线控制

        Delay(1);   //wait until stop condtion is in effect.

        //The pending bit will not be set after issuing stop condition.

        break;    

        }

        rIICDS=_iicData[_iicPt++];  //_iicData[0] has dummy.传送两次,数据和地址

        for(i=0;i<10;i++);      //for setup time until rising edge of IICSCL

        rIICCON=0xaf;       //resumes IIC operation.

        break;

    case SETRDADDR:

        //Uart_Printf("[S%d]",_iicDataCount);

        if((_iicDataCount--)==0)      //1,0

        {

        break;  //IIC operation is stopped because of IICCON[4]   

        }

        rIICDS=_iicData[_iicPt++];    //第一次开始传入数据地址,addr

        for(i=0;i<10;i++);  //for setup time until rising edge of IICSCL

        rIICCON=0xaf;       //resumes IIC operation.  在发送模式 读时,没有中断

        break;

    default:

        break;   

    }

}

Main(void)

{

unsigned int i;

U8 k;

Port_Init();

Uart_Init(0,115200);

Uart_Select(0);      //which Uart

rPCONF |= 0xa;        //port F的配置  00001010  IICSCL,IICSDA

rPUPF |= 0x0;           //port F的上拉电阻配置寄存器,允许上拉电阻连接到对应脚

rINTCON=0x1;            //支持向量中断      见书66页

pISR_IIC=(unsigned)IicInt;//中断服务,指向

rINTMSK&=~(BIT_GLOBAL|BIT_IIC);    //中断屏蔽寄存器,0允许,默认为1

rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xf);   //af  见书83页

//rIICADD=0x10;

//rIICSTAT=0x10;                               见书84页

for(i=0;i<255;i++)

{

Wr24C16(0xa0,(U8)i,i);

}

for(i=0;i<255;i++)

{

Rd24C16(0xa1,(U8)i,&k);

Uart_Printf("%d\n",k);

}

}

相关推荐