OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3674|回复: 2

求大神帮我看一下程序

[复制链接]

1

主题

1

帖子

0

精华

新手入门

积分
25
金钱
25
注册时间
2014-2-26
在线时间
0 小时
发表于 2015-7-29 22:10:31 | 显示全部楼层 |阅读模式
5金钱
本人要做一个数控电源,用Atmega16,数模转换器用PCF8591,IIC通信,再加OP07运放放大,仿真的时候,按钮一按下数模的输出有点延迟,数码管要等十几秒才显示电压的值
麻烦看一下代码
# include <iom16v.h>
# include <AVR_HJ-2G.h>
# include <macros1.h.>

# define uint unsigned int
# define uchar unsigned char

# pragrma data: code
uchar SEG[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//不带小数点的数码管段选
# pragrma data: code
uchar SEG7[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd, 0x87, 0xff,0xef};//带小数点的数码管段选


uint adc_val=0, dis_val=0;//全局变量
uchar cnt=0,i=0,temp=0x00,cnt4=0;

void delay (uint i)//延时函数
{
  uint j,k;
for (j=0; j<i;j++)
{
for (k=0; k<1141; k++)
;
  }
}

void IO_Init ()//IO口初始化
{
  DDRB=0xff;
PORTB=0x00;//PB口输出低电平,数码管的段选
 
DDRA=0xef;
PORTA=0x0f;//PA3-PA0设置为输出,PA4设置为输入 PA0-PA3数码管的位选
 
DDRD=0xff;
//PORTD|=BIT(2)|BIT(3);//PD2,3设置为带上拉电阻的输入 0000  1100
PORTD=0xff;
 
DDRC=0x00;
PORTC&=~BIT(2)&(~BIT(3));//PC2,PC3设置为带上拉电阻的输入,IIC通信
}
void Timer0_Init()//定时计数器0初始化
{
  TCNT0=0x83;//1ms的定时初值1000 0011
TCCR0=0x03;//定时器0的计数预分频取64
TIMSK=0x01;//使能T/C0中断
SREG=0x80;
}
void Timer2_Init()
{
  TCNT2=0x83;//1ms的定时初值1000 0011
TCCR2=0x03;//定时计数器2预分频取64
TIMSK|=BIT(6);//使能T/C2中断
}
void ADC_Init()//ADC模数转换器的寄存器的初始化
{
  ADMUX=0x04;//0000 0100 使用外部参考源,ADCL,ADCH左对齐,PA4作为模拟输入通道
ADCSRA=0xe0;//1110 0011 
}
/*void INT0_INT1 ()//中断寄存器的初始化
{
  MCUCR=0x0a;//INT0和INT1中断触发方式,下降沿触发0000 1010
GICR=0xc0;//开启INT0和INT1的中断使能位
SREG=0x80;//开启全局中断
}*/
void Init_devices()
{
  IO_Init();
Timer0_Init();
Timer2_Init();
ADC_Init();
//INT0_INT1();
}
uint ADC_Convert()
 {
   
   uint temp1,temp2;
 //ADC_Init();
 temp1=(uint)ADCL;
 temp2=(uint)ADCH;
 temp2=(temp2<<8)+temp1;//AD转换后的数字量所对应int型数,也就是整数
 return (temp2);
 }
 uint conv (uint i)
 {
   long x;
 uint y;
 x=(10240*(long)i)/1023;
 y=(uint)x;
 return y;
 }

/*I2C总线主机模式错误处理*/
void error(unsigned char type) 

 switch (type & 0xF8) 
 {  
  case 0x20:     /*址址写失败*/   
   /*stop 停止*/   
       TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);   break;  
  case 0x30:     /*数据写失败*/                  
       TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);   break;  
  case 0x38:     /*仲裁失败*/   break;  
  case 0x48:     /*址址读失败*/   
                    
       TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);   break;  
  }
}

/*I2C总线单字节写入*/
//这里是DA输出
unsigned char DA_write(unsigned char addr, unsigned char dd) 

  TWBR = 13; /*start 启动*/
// TWBR=(FOSC/baud-16)/2; 
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); 
  while (!(TWCR & (1 << TWINT))); 
  if ((TWSR & 0xF8) != 0x08) 
  {
  error(TWSR);  return 0;  

  /*SLA_W 芯片地址0x90 1001 0000与芯片硬件有关*/ 
  TWDR = 0x90; TWCR = (1 << TWINT) | (1 << TWEN); 
  while (!(TWCR & (1 << TWINT))); 
  if ((TWSR & 0xF8) != 0x18) 

  error(TWSR);  
  return 0;  
  } 
 /*addr 操作地址 这里写控制字 0x40标示DA输出使能*/
  TWDR = addr; TWCR = (1 << TWINT) | (1 << TWEN); 
  while (!(TWCR & (1 << TWINT))); 
  if ((TWSR & 0xF8) != 0x28) 
  {  
  error(TWSR);  
  return 0;  
  }  
 /*dd 写入数据 写入需要显示的电压值 */ 
  TWDR = dd; 
  TWCR = (1 << TWINT) | (1 << TWEN); 
  while (!(TWCR & (1 << TWINT))); 
  if ((TWSR & 0xF8) != 0x28) 
  {  
  error(TWSR);  
  return 0;  
  }  
 
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); 
   return 1;
 }
 
 void main ()
 {
   Init_devices();
 while (1)
 {
       DA_write(0x40, temp); 
if (cnt>5){
adc_val=ADC_Convert();
dis_val=conv(adc_val);
}

  }
 }
/*# pragma interrupt_handler int0:2  //INT0外部中断请求1的中断函数声明
int0 ()
{
   
temp++;
if (temp>=0x65)
{
temp=0x65;
}
}
# pragma interrupt_handler int1:3//INT1外部中断请求1的中断函数声明
int1 ()
{
  temp--;
if ( temp>=0x65)
{
temp=0x00;
}
                             
}*/
# pragma interrupt_handler Timer2:5
Timer2 ()
{   
 
  TCNT2=0x00;
cnt++;
PORTB=SEG[dis_val%10];//PB口先给第一位数码管的段选,给个位
PORTA&=~BIT(0);//给第一个数码管位选,让第一位数码管亮   
delay(5);
PORTA|=BIT(0);


PORTB=SEG[dis_val/10%10];//再给PA口十位数的段选,给第二位数码管
PORTA&=~BIT(3);
delay(5);
PORTA|=BIT(3);


PORTB=SEG[dis_val/100%10];
PORTA&=~BIT(2);
delay(5);
PORTA|=BIT(2);


PORTB=SEG7[dis_val/1000%10];
PORTA&=~BIT(1);
delay(5);
PORTA|=BIT(1);
}
# pragma interrupt_handler Timer0: 10
Timer0 ()
{
    uchar i;
  //SREG=0x80;
  TCNT0=0x83;
  i=PIND;
  delay(5);
  cnt4++;
  if (cnt4>5)
  {
  switch (i)
  {
     case 0xfb:  //1111 1011
 cnt4=0;
    temp++;
  if (temp>=0x65)
  {
   temp=0x65;
  }
  break;
 case 0xf7:  //1111 0111  1111 0111
  cnt4=0;
    temp--;
  if ( temp>=0x65)
  {
  temp=0x00;
  }
  break;
 default :
  cnt4=0;;
  }
  }
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

1592

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2622
金钱
2622
注册时间
2014-7-17
在线时间
350 小时
发表于 2015-7-30 00:04:29 | 显示全部楼层
回复

使用道具 举报

1

主题

374

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1327
金钱
1327
注册时间
2014-7-23
在线时间
422 小时
发表于 2015-7-30 02:10:40 | 显示全部楼层
应该是中断处理的不好,会调代码也是一种能力,Timer2 ()-->数码管、Timer0 ()-->按键??。。要开两个定时器
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 06:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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