关于按键控制LED和步进电机的问题
本帖最后由 jimmyfan 于 2013-4-12 17:07 编辑最近因为一些原因走上了AVR单片机这条路。
由于完全是自学,买了马老师的书,有一个简单的程序调试了很久了,身边又没有会人,一直没调出来,谁能给个参考啊
要求如下
总共五个按键,一个停止开始按键,
另外四个按键是每个都单独对应一个二极管,作为故障时使用(按下时停止对应的电机),
按下开始按键按顺序一到四个二极管依次点亮,每个二极管点亮的同时电机转动(电机速度要有不同,先正转后反转4S左右)
四个二极管都亮过之后数码管计数,此时电机转动(速度要不同),也就是这个程序可以循环工作
其实应该有四个电机,实际只用来一个电机,为了区分所以要速度不同
我写的程序,不能使电机,数码管,按键,LED,协调工作,老出错
作为新手很蛋疼啊
如果哪位会一个按键按下去LED亮,步进电机先正转后反转的也可以恢复给我看看,我看看自己到底哪出错了
非常感谢 踏踏实实从最基本的开始学习吧 本帖最后由 jimmyfan 于 2013-4-17 07:49 编辑
machao 发表于 2013-4-16 23:42 static/image/common/back.gif
踏踏实实从最基本的开始学习吧
自己在做的
这是我的程序
#include "iom16v.h"
#include "macros.h"
#include <AVR_PQ1A.h> //包含自定义常量头文件
#define uchar unsigned char
#define uint unsigned int
unsigned charF_Rotation={0xF1,0xF2,0xF4,0xF8}; //正转表格,换算成二进制 0000 0001,0000 0010,0000 0100,0000 1000
unsigned charB_Rotation={0xF8,0xF4,0xF2,0xF1}; //反转表格
#pragrma data:code
unsigned char const Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,};//0~9
void delay(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1141;j++);
}
}
//顺时针转动
void MotorCW()
{
unsigned char i;
{
DDRB = 0xFF;
for(i=0;i<4;i++) //4相
{
PORTB=F_Rotation;//输出对应的相 可以自行换成反转表格
delay(1); //改变这个参数可以调整电机转速 ,数字越小,转速越大
}
}
}
//逆时针转动
void MotorCCW()
{
unsigned char i;
{
DDRB = 0xFF;
for(i=0;i<4;i++) //4相
{
PORTB=B_Rotation;//输出对应的相 可以自行换成反转表格
delay(1); //改变这个参数可以调整电机转速 ,数字越小,转速越大
}
}
}
void MotorStop()
{
DDRB = 0xFF;
}
unsigned char KeyResult;
//键盘按下判断函数
uchar key_press() //按键子函数 ,带返回值的子函数
{
uchar j; //定义变量J
DDRD|=0X0F;//按键低4位输出,其它不变
PORTD|=0X0F;//按键低4位输出高电平,其它不变
DDRD&=0XF0;//按键低4位输入,其它不变
j=PIND; //对变量J赋值
j=j&0X0F;//00001111进行与运算,判断按键是否有按下
if(j==0X0F)//如果按键没有按下返回0,如按下返回1给key_press
{
return 0;
}
else
{
return 1;
}
}
//***********************************************************************
uchar key_scan() //扫描子函数
{
uchar key; //定义变量KEY
delay(10); //延时10MS再次确定按键是否有被按下
if(key_press())//判断按键 是否有被按下,则key_press为1,如按下则执行如下语句
{
key=PIND; //对变量KEY进行赋值
key&=0X0F; //进行运算判断一下是否真的有按下,如真的有按下,则有如下情况
switch(key) //条件语句
{
case 0X0E: //a0按下所对应的数据 ,并执行KEY为1
key=0X0E;
break;
case 0X0D: //a1按下
key=0X0D;
break;
case 0X0B: //a2按下
key=0X0B;
break;
case 0X07: //a3按下
key=0X07;
break;
default: //什么也没有按下
key=0;
break;
}
while(key_press());//判断一下是否有松开
}
else //如果没有按下则执行如下语句
{
key=0; //变量赋值16
}
return key; //返回KEY给key_scan扫描函数
}
void segg()//关数码显示管函数 可以自己设计数码管示显什么数字,新手没有学过数码管模块,本函数请暂时不要看
{
DDRA|=BIT(PA3); //PA3设置为输出状态
DDRA|=BIT(PA4); //PA4设置为输出状态
DDRB=0xff; //PB口设置为输出状态
PORTB=0xff; //发送模码
PORTA|=BIT(PA3); //PA3输出高电平,DU拉高
PORTA&=~BIT(PA3); //PA3输出低电平,DU拉低,段选锁存
PORTB=0xff; //发送为选关掉数码管显示
PORTA|=BIT(PA4); //PA4输出高电平,WE拉高
PORTA&=~BIT(PA4); //PA4输出低电平,WE拉低,位选锁存
DDRA|=BIT(PA2); //PA2设置为输出状态 用于LED流水灯控制IO口
PORTA&=~BIT(PA2); //PA2输出低电平,DU拉低,段选LED流水灯锁存
}
void light()//C语言主函数
{ DDRA=0xff; //PB0~7为输出状态
PORTA=0x01; //PB0为输出低电平,而其余为高电平,亦即打亮LED0
}
void lightt()//C语言主函数
{ DDRA=0xff; //PB0~7为输出状态
PORTA=0x02; //PB0为输出低电平,而其余为高电平,亦即打亮LED0
}
void lights()//C语言主函数
{ DDRA=0xff; //PB0~7为输出状态
PORTA=0x04; //PB0为输出低电平,而其余为高电平,亦即打亮LED0
}
void lightf()//C语言主函数
{ DDRA=0xff; //PB0~7为输出状态
PORTA=0x08; //PB0为输出低电平,而其余为高电平,亦即打亮LED0
}
void lightm()//C语言主函数
{ DDRA=0xff; //PB0~7为输出状态
PORTA=0x00; //PB0为输出低电平,而其余为高电平,亦即打亮LED0
PORTA=0x80;
}
void xian()
{ DDRA|=BIT(PA3); //PA3设置为输出状态
DDRA|=BIT(PA4); //PA4设置为输出状态
DDRB=0xff; //PB口设置为输出状态
PORTB=Number;
PORTA|=BIT(PA3); //PA3输出高电平,DU拉高
PORTA&=~BIT(PA3); //PA3输出低电平,DU拉低,段选锁存
PORTB=0xfe; //发送为选 6个数码管显示出数字
PORTA|=BIT(PA4); //PA4输出高电平,WE拉高
PORTA&=~BIT(PA4); //PA4输出低电平,WE拉低,位选锁存
//程式停止
}
void main(void)
{
uint i,q,j;
delay(1);
while(1)
{
while(1){
q=key_scan();
if (q==0x0E)
{
mark: light();//******************第一台电机转动指示灯
for (i=0;i<100;i++)
{ MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i=0;i<100;i++)
{ MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightt();//****************第二台
for (i=0;i<100;i++)
{ MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i=0;i<100;i++)
{ MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lights();//*******************第三台
for (i=0;i<100;i++)
{ MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i=0;i<100;i++)
{ MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightf();//*****************第四台
for (i=0;i<100;i++)
{ MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i=0;i<100;i++)
{ MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightm();
delay(500);
if(PORTA=0x80) goto mark;
}
}
}
}
抱歉,这个东西能自学成才的非常少。可能打击面大啦点,不高兴的朋友可以在这里“华山论剑”。
我有编写过一本教程,是国家级“十一五”规划教材,建议你从最基本的自学试一下。通过什么“十天学会单片机”成才的朋友,就不要多说了。
你的代码我瞄了一眼,什么DELAY(10),GOTO ......都是被我OUT的。 楼主还是踏踏实实的学习吧,能得到马老师亲自指点的人不多哦 本帖最后由 jimmyfan 于 2013-4-19 07:33 编辑
ITOP 发表于 2013-4-18 22:28 static/image/common/back.gif
楼主还是踏踏实实的学习吧,能得到马老师亲自指点的人不多哦
我很踏实的在学,不然也不会到论坛来,作为身边没有大神的初学者很多东西都得慢慢来摸索 本帖最后由 jimmyfan 于 2013-4-19 07:34 编辑
machao 发表于 2013-4-18 22:16 static/image/common/back.gif
抱歉,这个东西能自学成才的非常少。可能打击面大啦点,不高兴的朋友可以在这里“华山论剑”。
我有编写过 ...
您的书老早买了在看,因为别的循环一直不会用才用goto的,试了好几种循环,一直没成功,都急死了,因为是初学,身边没有会的人知道,全是自己瞎弄,看看您的书和逛逛这个论坛
上面程序的本意是按下键一启动,然后如果工作时按下键二停止,一直没成功,所以才到论坛求助的
谢谢马老师 jimmyfan 发表于 2013-4-19 07:26 static/image/common/back.gif
您的书老早买了在看,因为别的循环一直不会用才用goto的,试了好几种循环,一直没成功,都急死了,因为是 ...
循环用goto,楼主要补C语言了,推荐《C Primer Plus》中文第五版,看完这本书至少说C语言本身基础应该是相当不错了! 绿茶山人 发表于 2013-4-19 09:39 static/image/common/back.gif
循环用goto,楼主要补C语言了,推荐《C Primer Plus》中文第五版,看完这本书至少说C语言本身基础应该是 ...
本来用的while但是不能循环,求赐教 本帖最后由 绿茶山人 于 2013-4-19 11:08 编辑
jimmyfan 发表于 2013-4-19 10:36 static/image/common/back.gif
本来用的while但是不能循环,求赐教
楼主是想在while(1)中用while(1),然后在第二个while(1)中用第三个while(1)?不懂你为什么在main中用两个while(1), 下面我给你改了下代码,也没仔细弄,对不对就要你去试试了。void main(void)
{
uint i, q, j;
delay(1);
q = key_scan();
while (q == 0x0E) {
light(); //******************第一台电机转动指示灯
for (i = 0; i < 100; i++) {
MotorCW(); //顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i = 0; i < 100; i++) {
MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightt();//****************第二台
for (i = 0; i < 100; i++) {
MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i = 0; i < 100; i++) {
MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lights();//*******************第三台
for (i = 0; i < 100; i++) {
MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i = 0; i < 100; i++) {
MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightf();//*****************第四台
for (i = 0; i < 100; i++) {
MotorCW();//顺时针转动
}
delay(10);
MotorStop();//停止转动
delay(10);
for (i = 0; i < 100; i++) {
MotorCCW();//逆时针转动
}
delay(10);
MotorStop();//停止转动
delay(1);
lightm();
delay(500);
//if (PORTA = 0x80) //我想楼主这句应该是PORTA == 0x80
if (PORTA != 0x80)
break;
}
}
本帖最后由 jimmyfan 于 2013-4-19 12:27 编辑
绿茶山人 发表于 2013-4-19 10:49 static/image/common/back.gif
楼主是想在while(1)中用while(1),然后在第二个while(1)中用第三个while(1)?不懂你为什么在main中用两个wh ...
先谢过了,试了下,把if改成while(q==)之后按键没反应
页:
[1]