📄 main.c
字号:
//太阳能帽子 AVR ATMEGA48 驱动程序 2MHZ内部标定时钟 快速定位双PWM 恢复值50
//2007年4月10
//溶丝位 时钟 0010
#include"avr/io.h"
#include"avr/iom48.h"
#include"avr/signal.h"
#include "ad.h"
#include"avr/interrupt.h"
void yanshi(unsigned int x)
{
unsigned int y;
for(y=0;y<x;y++);
}
void shengyin(unsigned char x)
{
unsigned char cishu=0;
unsigned int changdu=0;
for(cishu=0;cishu<x;cishu++)
{
for(changdu=0;changdu<600;changdu++)
{
yanshi(31);
PORTD^=32; //声音
}
yanshi(40000);
}
}
unsigned char tem=0,tem10=0,tem100=0,tem1000=0;
unsigned char x=0;
SIGNAL(SIG_OVERFLOW0) //TO中断服务程序
{
TCNT0=255-78; // 10MS
tem+=1;
}
/*
SIGNAL(SIG_OVERFLOW2) //T2中断服务程序
{
}
SIGNAL(SIG_UART_RECV) //接收中断
{
}
SIGNAL(SIG_UART_TRANS) //发送完成中断
{
}
*/
void chushi(void)
{
//CLKPR=128;
//CLKPR=0;
WDTCSR=0B00011000;//KANMENGOU
WDTCSR=0B00101000;//4sKANMENGOU 启动看门狗 4秒方式
asm("WDR");
DDRB=14+16; //pb =in 无上拉
PORTB=255-6;
DDRD=0; //
PORTD=255; //
DDRC=0; //ADC
PORTC=255-7;
// 初始化PWM //
//==============================================================//
//TCCR1A 7 6 5 4 3 2 1 0//
// 7:6通道A比较输出模式 快速PWM模式 00普通断口 01取反 10匹配清零输出TOP恢复 11。。。
// 5:4通道B比较输出模式
// 3:2AB通道强制匹配输出
// 1:0 WGM11 WGM10 控制序列与TCCR1B中的 3:2 组合
//模式 WGM13 WGM12 WGM11 WGM10 定时器/计数器工作模式 计数器上限TOP //
//0 0 0 0 0 普通模式 0XFFFF
//1 0 0 0 1 8位相位修正PWM 0XFF
//2 0 1 0 0 TCT OCR1A
// 0 1 0 1 8位快速PWM 0XFF
// 1 1 1 0 快速PWM ICR1
TCCR1A=226;//242; //AB输出方式为匹配拉高 非匹配强制方式 快速PWM方式ICR1定义方式
TCCR1B=25; //AB输出工作于快速PWM方式ICR1定义 时钟源S/1
ICR1=80; //定义TOP数值 80=100KHZ 效率达到98%
OCR1A=80;//l40 80=0
OCR1B=0;//h38 0=0
//===================//初始化AD转换器
ADMUX=0B11000000; //AD工作于1.1V基准电压状态 同时设定AD0状态 数据是右对齐方式
//BIT 4-0 决定选择的AD位 0-7 代表AD0-AD7
ADCSRA=0B11000010; //启动AD,进入转换方式 工作于非中断方式 分频为S/4
//BIT6为转换完成标志 通过查询而进行读取 写1开始进行转换 变成0标志完成转变
//BIT4为转换完成标志 通过查询而进行读取 变成1表示完成变换 须用软件写1来完成清除标志
//初始化定时器T2
//=======================================================//
// TCCR2=7; //T2 1024分频
// TCNT0=55; // 1/20s
// TIMSK=1<<6; //准许T2中断bit6
/*
//初始化 UCSRB=216; //允许串口发送和接收,并响应接收完成中断
UBRRL= 103; //设置串口波特率为4800
UCSRC= ((1<<URSEL)+(1<<UCSZ1)+(1<<UCSZ0)); //帧结构为8位数据+1位stop位
*/
//初始化T0
TCCR0B=5; //TO 1024分频
TCNT0=78; //
TIMSK0|=1; //准许TO中断
SREG|=1<<7;
}
unsigned int ADDATA[5];
void pwmjia(void)
{
if(OCR1B<75)
OCR1B+=1;
else
OCR1B=75;
if(OCR1B>10)
OCR1A=OCR1B+2;
else
OCR1A=80;//禁止同步整流
}
void pwmjian(void)
{
if(OCR1B>4)
OCR1B-=1;
else
OCR1B=0;
if(OCR1B>10)
OCR1A=OCR1B+2;
else
OCR1A=80;//禁止同步整流
}
unsigned char shan1=0;
void shan(unsigned char x1,unsigned char x2)//闪烁次数 闪烁间隔总长度
{
shan1+=1;
if(shan1>=x2)
{shan1=0;
}
if(x1==1) //闪烁一次
{
if(shan1==2)
PORTD|=16;
else
PORTD&=255-16;
}
else
{
if(shan1==2||shan1==4)
{
PORTD|=16;
}
else
{
PORTD&=255-16;
}
}
}
int fudian(unsigned int x)
{
return x*37.236;
}
unsigned int setvin=210;//原始电压点 从EEPROM中来数据
unsigned int dianyain=210;//跟踪电压点
unsigned int jiange=0,yuandian1i=0,jianhoui=0,jiahoui=0,yuandian2i=0;
//采样总时间控制 原点电流 -。5电流 加0。5V电压后的电流 原点2电流
unsigned char jieduan=0,jieduan1=0,jieduan2=0,jieduan3=0,jieduan4=0;
//先采样原点电流 然后采样减电压后的电流 然后采样加电压后的电流 然后再采样原点电流 处理这些电流数据
//复位函数 功能恢复间隔跟踪 间隔一定时间后再次启动跟踪
void fuwei(void)
{
jiange=0;
jieduan=0;
yuandian1i=0;
yuandian2i=0;
jiahoui=0;
jianhoui=0;
jieduan4=0;
}
//处理跟踪得到的结果 跟踪数据得到最终处理
void chuligz(void)
{
if((jiahoui>jianhoui)&&(jiahoui>yuandian1i))
{//加跟踪成功
dianyain+=8;
fuwei();
jiange=300;//直接等待1S后再次启动跟踪
}
else
{
if((jianhoui>jiahoui)&&(jianhoui>yuandian1i))
{//减跟踪成功
dianyain-=8;
fuwei();
jiange=300;//直接等待1S后再次启动跟踪
}
else
{//跟踪都没有成功 等待下次跟踪
fuwei();
}
}
}
//跟踪主 程序 跟踪最大功率点功能
void genzong(void)
{
jiange+=1;
if(jiange>600)
{
switch(jieduan)
{
case 0: //阶段1 对原来的功率点取样电流 然后减0。5V电压 等待1S进入1模式
{PORTB^=16;
jieduan1+=1;
if(jieduan1<=5)//原电流点采样
{
yuandian1i+=ADDATA[2];
}
if(jieduan1==6)
{
yuandian1i=yuandian1i/5;
if(yuandian1i<10)//如果没有电流 则说明太阳能板没有阳光或者是跟踪点错误恢复原始原点
{
dianyain=setvin;
fuwei();
}
else
{
dianyain-=8;//电压降低越0。5V
}
}
if(jieduan1>200)//进入下个阶段
{
jieduan1=0;
jieduan=1;
}
}
break;
case 1://阶段2 对-0。5V后的功率点取样电流然后加1V后等待1S进入模式2
{
//PORTB&=255-16;
jieduan2+=1;
if(jieduan2<=5)//原电流点采样
{
jianhoui+=ADDATA[2];
}
if(jieduan2==6)
{
jianhoui=jianhoui/5;
dianyain+=16;//提高电压0。5V
}
if(jieduan2>200)//进入下个阶段
{
jieduan2=0;
jieduan=2;
}
}
break;
case 2://阶段3 取样加0。5V后电流 然后恢复电压到原点 等代2S后进入下个阶段
{
jieduan3+=1;
if(jieduan3<=5)//原电流点采样
{
jiahoui+=ADDATA[2];
}
if(jieduan3==6)
{
jiahoui=jiahoui/5;
dianyain-=8;//恢复电压到原点
}
if(jieduan3>200)//进入下个阶段
{
jieduan3=0;
jieduan=3;
}
}
break;
case 3://阶段4 取样电流然后于阶段1取样电流比较 ,比较基本相同 进行于模式2的取样比较,处理大小
{
jieduan4+=1;
if(jieduan4<=5)//原电流点采样
{
yuandian2i+=ADDATA[2];
}
if(jieduan4==6)//原电流点采样
{
yuandian2i=yuandian2i/5;
jieduan4=0;
if(yuandian1i>yuandian2i)//光线影响处理程序
{
if((yuandian1i-yuandian2i)>580)//如果两次原点相差20则受到阳光强度影响 启动再次取样比较
{
fuwei();
jiange=0;//等待0.5S后从新启动跟踪
}
else
{//一切正常处理程序
chuligz();
}
}
else
{
if((yuandian2i-yuandian1i)>580)//如果两次原点相差30则受到阳光强度影响 启动再次取样比较
{
fuwei();
jiange=0;//等待0.5S后从新启动跟踪
}
else
{//一切正常处理程序
chuligz();
}
}
}
}
break;
}
}
}
unsigned char aa=0;
int main(void)
{
chushi();
PORTB=255-8;
for(;;) //事实程序在这里面循环
{
if(tem>=1)
{
tem=0;
tem100+=1;
if(tem100>19)
{tem100=0;
//100ms
tem1000+=1;
if(tem1000>=10)
{//节拍1000
tem1000=0;
//1000ks
// asm("WDR");
}//节拍1000END
//100ms
//100msEND
}
//10ms
genzong();//跟踪功率点程序 完成最大功率点跟踪
//10msend
}
AD(&ADDATA[0]);
//自动电压电流调节
aa+=1;
if(aa>20)
{aa=0;
/*
ADMUX=0B11000000;
ADCSRA|=16+64;
for(;!(ADCSRA&16);)
ADDATA[0]=ADC; //读取AD0
*/
//电压跟随 完成最大功率点的电压限制
if(ADDATA[0]>dianyain)//465 = 1.5v
{
pwmjia();
}
else
{
//if(ADDATA[0]<dianyain-2)
//{
pwmjian();
//OCR1A=80;
//OCR1B=0;
//}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -