西电微机系统课程设计步进电机开环控制系统

**

微机系统与应用课程设计

课题二 步进电机开环控制系统设计**
一、程设计目的

  1. 掌握微机系统总线与各芯片管脚连接方法,提高接口扩展硬件电路的连接能力。
  2. 加深对 A/D 和并行接口芯片的工作方式和编程方法的理解。
  3. 搞懂步进电机的工作原理及控制方式,掌握开环控制系统的设计思路和实现方法。

二、课程设计的内容
手动调节电位器旋钮(0V~5V),通过 ADC0809 模拟输入水库水位 0 米~50 米,CPU收到水位信号后,根据水位高度控制步进电机(水闸)进行调节。

三、系统功能与设计要求

1.基本功能要求
手动调节电位器旋钮,步进电机根据水位实时调节水闸。设水闸全部打开需要逆时针旋转 10 圈 (10 x 360°)度。随着上游进入水库的水流量变化,水库水位不断变化(手动调节电位器旋钮),每到一定高度,步进电机顺时针(关)或逆时针(开)旋转一定的角度调节水闸开启程度,从而控制水库水位在 10~50 米之间。调节精度控制在±5%。
水位与水闸控制开启控制表
水位高度 H(米) 水闸开启程度(%) 指示灯
0≤H< 10 0% (0 圈) 关闸蓄水,水位超低报警(黄 led 闪烁)
10≤H< 20 20%(2 圈) 正常调节(绿 LED 亮)
20≤H< 30 40%(4 圈) 正常调节(绿 LED 亮)
30≤H< 40 60%(6 圈) 正常调节(绿 LED 亮)
40≤H< 50 80%(8圈) 正常调节(绿 LED 亮)
H≥50 100%(10 圈) 开闸泄洪,水位超高报警 (红 led 闪烁)
注:当实验结束要立即关闭电源,否则一直停留在某一相上会使电机发热。

2.发挥部分
(1)增加速度调节功能。水位在10~40米期间,步进电机中速转动,水位低于10(水位过低)或高于 40 米(水位过高)时,步进电机高速转动。
(2)增加实时水位显示。用数码管 DLED 高两位显示当前水位(00~50 米)。
(3)增加水闸开启程度显示。用数码管 DLED 低两位实时显示水闸开启程度(00~10圈)。
四、设计思路
手动调节电位器旋钮(05V),模拟水库水位变化(050 米),电位器的输出接入ADC0809的一个输入通道。通过编程将模拟量实时采集并转变为对应的数字量,CPU 通过查询数字量可计算出实际的水位。如果水位过低(或过高)则关闭(或打开)水闸,如果在正常范围内,根据调节规律查出相应的水闸开启程度,并与上次开启程度比较,计算出调节步进电机的角度、方向(步进电机的步进角为 xx 度),然后控制步进电机进行相应转动,调节水闸,从而达到控制水位的目的。LED 指示灯可以通过使用基本并行 I/O 接口(74LS273)控制显示,DLED 数码管可以采用系统提供的相应模块,控制可以通过 8255 可编程并行接口,如:PA口的底四位(PA0~PA3)控制步进电机,PB 口和 PC 口的低四位(PC0~PC3)控制数码管的段,位。

五、操作步骤

1.提交设计方案

包括:控制功能实现方案,编程语言硬件设计方案及硬件连线图,硬件支持环境和软件支持的环境要求

2.方案审核

系统设计方案经过指导老师审核后,方可以实施操作。

3.硬件系统实现

按照硬件设计方案及硬件连线图连线,经过指导老师认可后,加电并观察是否正确。如果发现异常,立刻关掉电源,查明原因,解决问题后,再加电观察。

4.按照功能要求编程,运行,调试

六.实验步骤
1.实验开始前,首先分别对AD0889、8255、数码显示管、步进电机进行分单元检测,确保每一个器件都可以正常工作。
2.通过调节电位器获得连续数,通过AD0809数码转化器转化为0255的离散数字,在程序中将数据转化为050的数字,用来表示水位。
3.程序中对水位进行判断,然后控制步进电机的转动方向和转动圈数,并通过并行接口8255,在数码管DLED上显示水位示数和电机转动圈数,在LED指示灯上显示水位情况。
七、课程设计实验环境:

  1. 硬件配置:
    微机一台 (Pentium 4)
    微机接口技术实验箱 一个
    ISA – PCI 转接卡 一块
    连接电缆 一条
    万用表 一块
    微机接口技术实验讲义 一本
    连接导线
  2. 软件环境:
    Windows XP/2000/Win 7 平台
    Visual C++ 6.0 编译器

八.线路连接图
1.总连接图
在这里插入图片描述
2.地址和数据线
在这里插入图片描述
3.LED指示灯
在这里插入图片描述
4.AD0809数码转换器
在这里插入图片描述
5.8255和DLED数码管
在这里插入图片描述
九.源代码
// AD0809SDlg.cpp : implementation file
//
#include “stdafx.h”
#include “AD0809S.h”
#include “AD0809SDlg.h”
#include “…\qth9054fun.h”
#include “math.h”
//端口地址定义
#define P8255_A 0x0000
#define P8255_B 0x0001
#define P8255_C 0x0002
#define P8255_MODE 0x0003
#define Ls273 0x0040
#define uchar unsigned char
#define uint unsigned int
//kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
#define AD0809 0x20
//DLED数字定义
uchar table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//need define
//LED颜色定义
enum COLOR {
RED = 0x70,GREEN = 0xb0,YELLOW=0xd0,BLACK=0xf0
} color;
BYTE dsbuf[4]={0,0,0,0};
//end
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = FILE;
#endif
CWinThread *Thread_Comd; //要创建的两个线程
HWND hWnd;
BOOL ISSTART=false;
int cur=10000;
//通过水位,设置颜色
enum COLOR getcolor(BYTE d)
{
if(d<10) return YELLOW;
if(d>=50) return RED;
return GREEN;
}
int CUR_POSITION = 0;
int PPOSITION = 0;
int flashcnt = 0;
int lastflashcnt = 0 ;
bool flash = true;
//刷新DLED显示
void disp()
{
BYTE b;
int a;
if(PPOSITION<2 || PPOSITION>=10){
if(flash){
color = BLACK;
}
if(abs(flashcnt-lastflashcnt) > 500){
flash = flash?false:true;
lastflashcnt = flashcnt;

	}
}
flashcnt++;
for(a=0,b=0x01;a<4;a++,b=b<<1)
{	
	IO8bWrite(P8255_B,color);		//关闭显示器*****************增加
	IO8bWrite(P8255_A,dsbuf[a]);
	IO8bWrite(P8255_B,color+b);
//	Sleep(1);//*****************删除
}	
//IO8bWrite(P8255_B,0x60);		//关闭显示器

}
BYTE depth=0;
int pt;
CAD0809SDlg * pDlg;
//DLED和LED的数据控制
void basefresh(){
IO8bWrite(AD0809,0);
depth=IO8bRead(AD0809);
depth= depth50/230;
//depth and light show control per time
pt = ++pt;
pt = pt%4;
switch(pt){
case 0: dsbuf[pt]=table[depth/10]; break;
case 1: dsbuf[pt]=table[depth%10];break;
case 2: dsbuf[pt]=table[CUR_POSITION/10];break;
case 3: dsbuf[pt]=table[CUR_POSITION%10];break;
}
PPOSITION = ((depth/10)2);
color = getcolor(depth);
}
//电机转机刷新
void freshRotation(int t=10){//转间刷新
t
=2;
if(PPOSITION >= 2 && PPOSITION <8 ) t
=2;

while(t--){
	basefresh();
	disp();
	pDlg->SetDlgItemInt(IDC_EDIT1, (int)depth);	
}

}
//四相八步电子控制数据
BYTE ROT[8]={0x80,0x90, 0x10, 0x30, 0x20, 0x60, 0x40, 0xC0};
//电机旋转一圈的控制
void moveClock(bool po) //控制转向
{
int T =100;
//defien a circle of positive
int i=0;
if(po){
for(;i<45;i++){
IO8bWrite(P8255_C, ROT[(cur+i)%8]); freshRotation(T);
}
cur+=i;
CUR_POSITION++;
}else{
for(;i<45;i++){
IO8bWrite(P8255_C, ROT[(cur-i)%8]); freshRotation(T);
}
cur-=i;
CUR_POSITION–;
}
IO8bWrite(P8255_C, 0x0);
freshRotation(500);
}
//初始化和主循环
UINT Comd(LPVOID pParam)
{
pDlg = (CAD0809SDlg*)AfxGetMainWnd();
CString str;
IO8bWrite(P8255_MODE,0x80);
IO8bWrite(AD0809,0);
depth=IO8bRead(AD0809);
depth= depth50/251;
bool first = true;
while(ISSTART) {
basefresh();
if(first){
PPOSITION=CUR_POSITION = (depth/10)2;
first = false;
}
disp();
pDlg->SetDlgItemInt(IDC_EDIT1, (int)depth);
if((depth/10)2 == CUR_POSITION){
}else if((depth/10)2 < CUR_POSITION){
moveClock(false);
}else if((depth/10)2 > CUR_POSITION){
moveClock(true);
}
}
return 0;
}
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange
pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange
pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CAD0809SDlg dialog
CAD0809SDlg::CAD0809SDlg(CWnd
pParent /
=NULL
/)
: CDialog(CAD0809SDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CAD0809SDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CAD0809SDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAD0809SDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAD0809SDlg, CDialog)
//{{AFX_MSG_MAP(CAD0809SDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CAD0809SDlg message handlers
BOOL CAD0809SDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add “About…” menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application’s main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
if (!Init9054()) return 0;
Thread_Comd=AfxBeginThread(Comd,NULL,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED); //创建KEYDOWN线程
hWnd=this->GetSafeHwnd(); //取得窗口句柄
return TRUE; // return TRUE unless you set the focus to a control
}
void CAD0809SDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CAD0809SDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CAD0809SDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CAD0809SDlg::OnOK()
{
// TODO: Add extra validation here
UpdateData(true);
if (!ISSTART) {
ISSTART=true;
Thread_Comd->ResumeThread();
}
// CDialog::OnOK();
}
void CAD0809SDlg::OnCancel()
{
// TODO: Add extra cleanup here
UpdateData(true);
ISSTART=false;
Cleanup();
CDialog::OnCancel();
}
十.实验总结
通过这次课程设计,让我更深刻地了解到微机系统的一些知识,并对课本上学习到的知识,经过动手实践,加深了理解,在和队友合作的过程中,也增加了合作的技巧。
在具体实验时,首先要对实验有一个全局的把握,设计实验框架,然后分模块实现。在进行实验之前,一定要对每一个实验器件分别进行测试,保证每一个器件都能正常工作,然后开始具体实验。实验中要学习懂得如何排错,当出现错误的时候,要确定是程序错误还是硬件连线错误,如果确认是硬件错误,要分模块测试,确定具体出错的器件或连线,然后更正错误。

  • 4
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值