ATmega128串口通信程序(中断方式)
ATmega128串口通信程序(中断方式)
2011-06-05 20:08:10| 分类:单片机程序编写| 标签:|字号大中小订阅程序采用IAR系统编译,实现使用串口调试助手收发数据的功能
#include<iom128.h>
#include<inavr.h>
#include<string.h>
#define INT8U unsigned char
#define INT16U unsigned int
#define UDRIE0 5
/* UART Buffer Defines */
#define UART0_RX_BUFFER_SIZE 128
#define UART0_TX_BUFFER_SIZE 128
/* Static Variables */
static unsigned char UART0_RxBuf[UART0_RX_BUFFER_SIZE];
static volatile unsigned char UART0_RxHead;
static volatile unsigned char UART0_RxTail;
static unsigned char UART0_TxBuf[UART0_TX_BUFFER_SIZE];
static volatile unsigned char UART0_TxHead;
static volatile unsigned char UART0_TxTail;
static unsigned char UART0_Flag=1;
void USART_INIT( void )
{
UBRR0H = 0x00;
UBRR0L = 0x0B;//9600 at 1.8432M
UCSR0A = 0x20;
UCSR0B = 0xD8;//开接收结束中断,发送结束中断接收使能,发送使能
UCSR0C = 0x06;//异步模式,1位停止位,8位数据位
UDR0 = 0x00;//清空数据寄存器
UART0_RxTail = 0;
UART0_RxHead = 0;
UART0_TxTail = 0;
UART0_TxHead = 0;
__disable_interrupt();//关全局中断
}
void Tran_Byte( INT8U sdata )
{
if(UART0_Flag == 0)
{
UDR0 = sdata;
UART0_Flag = 1;
}
else
{
UART0_TxBuf[UART0_TxHead] = sdata;
UART0_TxHead++;
if(UART0_TxHead >= UART0_TX_BUFFER_SIZE) UART0_TxHead = 0;
}
__enable_interrupt();
}
void Send_String( INT8U *string )
{
INT8U temp;
while(1)
{
temp = *string;
Tran_Byte(temp);
string++;
if(*string == 0x00)
break;
}
}
INT8U HaveDataRxd( void )
{
if(UART0_RxHead != UART0_RxTail)
return 1;
else
return 0;
}
INT8U GetDataFromRxdBuf( void )
{
INT8U temp;
temp = UART0_RxBuf[UART0_RxTail];
UART0_RxTail ++ ;
if( UART0_RxTail >= UART0_RX_BUFFER_SIZE ) {
UART0_RxTail = 0 ;
}
return temp;
}
//清空接收缓冲区。
void UART_ResetRxBuffer( void )
{
UART0_RxHead = 0;
UART0_RxTail = 0;
}
int main( void )
{
DDRA = 0xFF;PORTA = 0xFF;
DDRE = 0xFE;
INT8U tab;
USART_INIT();
__enable_interrupt();//开全局中断
while(1)
{
__delay_cycles(10000);
while(!HaveDataRxd());
tab = GetDataFromRxdBuf();
__delay_cycles(10000);
Tran_Byte(tab);
}
}
#pragma vector=USART0_RXC_vect
__interrupt void USART0_RX( void )
{
INT8U data;
INT8U status;
data = UDR0; /* read the received data */
status = UCSR0A;
if((status & 0x18) == 0x00)
{
UART0_RxBuf[UART0_RxHead] = data;
UART0_RxHead ++;
if(UART0_RxHead == UART0_RX_BUFFER_SIZE) UART0_RxHead = 0;
}
}
#pragma vector=USART0_TXC_vect
__interrupt void USRAT0_TX( void )
{
INT8U temp;
/* check if all data is transmitted */
if(UART0_TxHead != UART0_TxTail)
{
/* calculate buffer index */
temp = UART0_TxBuf[UART0_TxTail];
UDR0 = temp;
UART0_TxTail ++;
if(UART0_TxTail >= UART0_TX_BUFFER_SIZE) UART0_TxTail = 0;
}
else
{
UART0_Flag = 0;
}
}。
基于Atmega128和SJA1000的CAN总线通信应用设计
0 引 言
随着单片机在工业控制领域的应用越来越广 泛, 在很多场合都需要用单片机对现场的信息进行 采集与处理, 并与主机进行通信, 但往往会遇到长远 距离和大数据量传输不足的问题, 通过 C A N总线可 以解决此问题。本文用 A t m e g a 1 2 8实现主从节点相 互通信的简单电路, 但此单片机不能独立地满足要
第4 1卷第 1期 5 2 2 0 1 4年 2月 2 5日
数 字 通 信 D i g i t a l C o m m u n i c a t i o n
V o l 4 1 ,N o . 1 F e b . 2 5 2 0 1 4
D O I : 1 0 . 3 9 6 9 / j . i s s n . 1 0 0 1 3 8 2 4 . 2 0 1 4 . 0 1 . 0 1 4
本文 芯 片 工 作 在 P e l i C A N 模 式 下, 将芯片的 M O D E引脚置 1 , 即让 S J A 1 0 0 0的外部控制总线采3 Βιβλιοθήκη n t e l 模式 [ 。 用I
1 . 2 S J A 1 0 0 0芯片初始化 设置芯片工作在 P e l i C A N模式下, 初始化流程 图如图 1所示。
2 ] 能力和检错、 纠错能力 [ 。
图1 S J A 1 0 0 0初始化流程图
2 设计思路
2 . 1 硬件设计思路 在现实生活中, 例如医疗行业等, 涉及到多个控 制系统与服务器进行信息交换, 有时候需要大量远 距离的数据通信。传统的通信方式比如串口通信 I I C满足不了应用需求, 而主流的单片机芯片自身没 有集成 C A N总线的控制器和对应的收发器。针对以 上情况, 我们采用 S J A 1 0 0 0的控制器和 M C P 2 5 5 1收 发器来扩展 A t m e g a 1 2 8的 C A N总线接口, 实现节点 之间的通信。 A t m e g a 1 2 8的 P A口连接 S J A 1 0 0 0的 连接思路: A D口( 地址 / 数据总线) , P G 2口接 S J A 1 0 0 0的 A L E / A S 口( 输入信号模式) , P G 1口接 S J A 1 0 0 0的 / R D / E 口, P G 0口接 S J A 1 0 0 0的 / WR口, P D 0口接 S J A 1 0 0 0 [ 2 ] 的/ I N T口 。
ATmega128几个常用程序例子
ATmega128几个常用程序例子ATMEGA128相关例程自己学avr单片机已经有相当一段时间了,一开始用的是atmega128,觉得不是很好用。
于是自己去买了一块16L的芯片,觉得还行。
一开始用的是ICC AVR,应为它用起来比较简单,不像winavr那样,要写个Makefie,比较的麻烦,但icc avr的缺点是太过于简陋,调试程序时,感觉不是很好。
后来经同学介绍,用起了winavr,其实也是比较的简单,只不过要加一个makefile而已,其实makefile可以用软件自带的组建自动生成,只需修改几个参数就可以用。
后来又用起了code vision avr,虽然不太习惯,也谈不上不好用.需要注意的是,三个不同的软件所带的同文件不一样。
icc avr 是iom128v.h(姑且以128为例),winavr是avr/io.h,不过makefile中要设置芯片为atmega128.而cvavr则是mega128.h。
记得一开始的时候,我对这些不同的同文件不是很理解,是从一个学长那里了解到,才弄明白的。
其实前两个软件只需把头文件稍微改一下基本上可以通用。
而最后一个软件的中断的写法似乎不太一样,因而和钱两个软件的兼容性是最差的。
总体说winavr给人的感觉是比较专业自己学习时多总结吧!1、流水灯/*硬件环境:atmega128开发板软件环境:CodeVisionAVR-C*/#include <mega128.h>#define uchar unsigned char#define uint unsigned intuchar cnt;void timer1_init(){TCCR1B=0X00; //先停止定时器1TCNT1H=0XF0; //设定定时器初值TCNT1L=0XBE;TCCR1A=0X00; //启动定时器1TCCR1B=0X05; //使用1024分频}interrupt [TIM1_OVF] void timer1_ovf_isr(void){TCNT1H=0XF0; //重载定时器初值TCNT1L=0XBE;DDRE|=1<<2;PORTE|=1<<2;DDRA=0xff;PORTA=cnt; //输出led的值到端口Bcnt++;if(cnt==255)cnt=0;}void main(){//DDRB=0XFF;SREG|=0X80;TIMSK=0X04;timer1_init();while(1){;}}2、AD转换+数码管显示/*************************************************************** ************//*ADC测试程序*//*目标器件:ATmega128 *//*晶振:RC 8MHZ *//*编译环境:ICCAVR 7.13A *//*E-Mail:number007cool@ *//*时间:2010年11月13日*///Aref接AVCC(+5V),采用Aref作参考电压/*用数码管显示AD转换的结果*//*************************************************************** ************//*********************************包含头文件********************************/#include <iom128v.h>#include <macros.h>/********************************数码管段码表*******************************/extern const unsigned char tab[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*********************************全局变量**********************************/unsigned int adc_rel=0;/*************************************************************** *************函数功能:ADC初始化函数入口参数:出口参数:**************************************************************** ************/void adc_init(void){DDRF&=0XFE; //PORTF0设置为输入,即作为ADC0口输入模拟电压PORTF&=0XFE; //PORTF0设置为输入低电平ADCSRA=0x00; //关ADCADMUX = 0X00; //采用Aref作为参考电压,ADC0单端输入,右对齐ACSR=(1<<ACD);ADCSRA =(1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1); //ADEN,启动ADC;ADSC,ADC开始转换;ADIE,ADC中断使能;ADPSx,设置分频因子64 }/*************************************************************** *************函数功能:ADC中断函数入口参数:出口参数:**************************************************************** ************/#pragma interrupt_handler adc_isr:iv_ADCvoid adc_isr(void){//int data_h,data_l;//data_l=ADCL;//data_h=ADCH;ADCSRA = 0x00;ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIE);adc_rel=ADC;/*if(adc_rel>0x1ff){PORTA|=1<<2;}elsePORTA&=~(1<<2);*/}/*************************************************************** *************函数功能:延时子程序入口参数:出口参数:**************************************************************** ************/void delay(void){int i;for(i=0;i<1800;i++);}/*************************************************************** *************函数功能:显示子程序入口参数:k出口参数:**************************************************************** ************/void display(unsigned int k)//发光二极管显示初始化{DDRE|=1<<2;PORTE|=1<<2;DDRA=0XFF;PORTA=k;}#define SS 0#define SCK 1#define MOSI 2#define MISO 3#define SS_H() PORTB|=(1<<SS)#define SS_L() PORTB&=~(1<<SS)#define led0_en() {DDRB|=1<<4;PORTB|=(1<<4);} //开第一个数码管的位选#define led0_dis() {DDRB|=1<<4;PORTB&=~(1<<4);} //关第一个数码管的位选#define led1_en() {DDRB|=1<<5;PORTB|=(1<<5);}#define led1_dis() {DDRB|=1<<5;PORTB&=~(1<<5);}#define led2_en() {DDRB|=1<<6;PORTB|=(1<<6);}#define led2_dis() {DDRB|=1<<6;PORTB&=~(1<<6);}#define led3_en() {DDRB|=1<<7;PORTB|=(1<<7);}#define led3_dis() {DDRB|=1<<7;PORTB&=~(1<<7);}#define OE 7#define point 3#define dp 7#include <iom128v.h>#include <macros.h>const unsigned char table[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,40x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,9 0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,f volatile unsigned char led_buffer[4];void delay_1us(void) //1us延时函数{asm("nop");}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}/*完成spi的初始化*/void spi_init(void){DDRB |= (1<<MOSI)|(1<<SCK)|(1<<SS);//设置MOSI,SCK输出SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);//使能SPI,主机模式}/*spi主机传送数据*/void SPI_MasterTransmit(char Data){/* 启动数据传输*/SPDR = Data;/* 等待传输结束*/while(!(SPSR & (1<<SPIF)))}/*完成对HC595的初始化*/void HC_595_init(void){DDRC |= (1<<OE); //设置PORTC7为输出PORTC &= (1<<OE); //输出高电平,使能595PORTB = 0x0F; //同时打开四个数码管的位选spi_init();led_buffer[0]=16; //初始化数码管段码led_buffer[1]=16;led_buffer[2]=16;led_buffer[3]=16;}/*HC595完成传送数据*/void HC_595_OUT(unsigned char data){SS_L();SPI_MasterTransmit(data);SS_H();}void leddis_update(void){/*最低位数码管,第四个数码管*/if(point==0)HC_595_OUT(table[led_buffer[3]]|(1<<dp)); elseHC_595_OUT(table[led_buffer[3]]);led0_en();delay_nus(60);led0_dis();if(point==1)HC_595_OUT(table[led_buffer[2]]|(1<<dp)); elseHC_595_OUT(table[led_buffer[2]]);led1_en();delay_nus(60);led1_dis();if(point==2)HC_595_OUT(table[led_buffer[1]]|(1<<dp));HC_595_OUT(table[led_buffer[1]]);led2_en();delay_nus(60);led2_dis();/*最高位数码管,第一个数码管*/if(point==3)HC_595_OUT(table[led_buffer[0]]|(1<<dp));elseHC_595_OUT(table[led_buffer[0]]);led3_en();delay_nus(60);led3_dis();}void display_led(unsigned int data){if(data>9999){HC_595_OUT(0xFF);//当计数大于9999时,四个数码管同时输出8 PORTB|=((1<<4)|(1<<5)|(1<<6)|(1<<7));}else if(data>999){led_buffer[0]=data/1000;led_buffer[1]=(data%1000)/100;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else if(data>99){led_buffer[0]=data/1000; //关闭最高位的那个数码管led_buffer[1]=(data%1000)/100;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else if(data>9){led_buffer[0]=data/1000;led_buffer[1]=16;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else{led_buffer[0]=data/1000;led_buffer[1]=16;led_buffer[2]=16;led_buffer[3]=data%10;leddis_update();}}volatile unsigned int countnum=0;void timer1_init(void){TCCR1B = 0x00; //stopTCNT1H = 0x8F; //setupTCNT1L = 0x81;OCR1AH = 0x70;OCR1AL = 0x7F;OCR1BH = 0x70;OCR1BL = 0x7F;OCR1CH = 0x70;OCR1CL = 0x7F;ICR1H = 0x70;ICR1L = 0x7F;TCCR1A = 0x00;TCCR1B = 0x04; //start Timer}#pragma interrupt_handler timer1_ovf_isr:15 void timer1_ovf_isr(void){TCNT1H = 0x8F; //reload counter high value TCNT1L = 0x81; //reload counter low value countnum++;if(countnum>9999) countnum=0;}void init_devices(void){CLI(); //disable all interruptstimer1_init();TIMSK = 0x04; //timer interrupt sourcesSEI(); //re-enable interrupts}/*************************************************************** *************函数功能:主程序入口参数:出口参数:**************************************************************** ************/void main(void){init_devices();HC_595_init();adc_init();SEI();//开全局中断变量display(0);while(1){delay();display_led(adc_rel/1024.0*5*1000);}}3、对EEPROM进行读写操作/************************************************文件:main.c用途:注意:内部8M晶振************************************************/#include "config.h"/*向EEPROM里面写入数据输入量:地址,数据*/void EEPROM_write(unsigned int uiAddress,unsigned char ucData){while(EECR&(1<<EEWE)); //等待上一次写操作结束EEAR = uiAddress; //地址EEDR = ucData; //数据EECR |=(1<<EEMWE); //置位EEMWE,主机写使能EECR |=(1<<EEWE); //置位EEWE,写使能,启动写操作}/*从EEPROM指定的地址里面读出相应的数据*/unsigned char EEPROM_read(unsigned int uiAddress){while(EECR&(1<<EEWE)); //等待上一次写操作结束EEAR = uiAddress; //设置地址寄存器EECR |=(1<<EERE); //读使能return EEDR; //返回读入EEDR里面的数据}void main(void){unsigned char temp=123;unsigned char data;HC_595_init();EEPROM_write(0x01,temp);data=EEPROM_read(0x01);while(1){Seg7_Led_display(data); //调用显示函数将写入的数据又读出来}}文件: eeprom12.rar大小: 40KB下载: 下载4、定时器0(轮循方式)/*定时器0和2(均为八位的定时计数器)有四种工作模式,此例是工作在普通模式。
ATmega128的中断系统
任意电平变化触发表示只要引脚上有逻辑电平的变化就会 产生中断申请(不管是上升沿还是下降沿都引起中断触发) 产生中断申请(不管是上升沿还是下降沿都引起中断触发)
4种触发方式中,还有以下的一些不同的特点: 种触发方式中,还有以下的一些不同的特点: 种触发方式中 1.低电平触发是不带中断标志类型的,即只要中断输入引脚PD2 低电平触发是不带中断标志类型的,即只要中断输入引脚 低电平触发是不带中断标志类型的 保持低电平, 或PD3保持低电平,那么将一直会产生中断申请。 保持低电平 那么将一直会产生中断申请。 2.MCU对INT0和INT1的引脚上的上升沿或下降沿变化的识别 对 和 的引脚上的上升沿或下降沿变化的识别 触发),需要I/O时钟信号的存在 ),需要 时钟信号的存在( 时钟同步检测), (触发),需要 时钟信号的存在(由I/O时钟同步检测), 时钟同步检测 属于同步边沿触发的中断类型。 属于同步边沿触发的中断类型。 3.MCU对INT2的引脚上的上升沿或下降沿变化的识别(触 对 的引脚上的上升沿或下降沿变化的识别( 的引脚上的上升沿或下降沿变化的识别 ),以及低电平的识别 触发)是通过异步方式检测的, 以及低电平的识别( 发),以及低电平的识别(触发)是通过异步方式检测的,不 需要I/O时钟信号的存在。因此,这类触发类型的中断经常作 需要 时钟信号的存在。因此, 时钟信号的存在 为外部唤醒源,用于将处在Idle休眠模式,以及处在各种其它 休眠模式, 为外部唤醒源,用于将处在 休眠模式 休眠模式的MCU唤醒。这是由于除了在空闲(Idel)模式时, 唤醒。 休眠模式的 唤醒 这是由于除了在空闲( )模式时, I/O时钟信号还保持继续工作,在其它各种休眠模式下,I/O时 时钟信号还保持继续工作, 时钟信号还保持继续工作 在其它各种休眠模式下, 时 钟信号均是处在暂停状态的。 钟信号均是处在暂停状态的。
AVR_128_spi串口通信程序
UCSR1B=(1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);//发送接收使能,接收中断使能
UCSR1C=(1<<UCSZ11)|(1<<UCSZ10);//8位数据,UCSZ12,11,10共同确定
DDRD|=BIT(3); //设置发送口为输出
}
/*串口0单字符发送,查询方式*/
{
UCSR1B = 0x00; //禁止发送和接收
UCSR1A = 0x02; //倍速异步模式 USX0=1
UBRR1L=(Crystal/8/Baud1-1)%256; //根据数据手册的计算法
UBRR1H=(Crystal/8/Baud1-1)/256; //如果不是倍速则(Crystal/16/Baud1-1)
Flag1=1;
UCSR1B|=BIT(RXCIE1);//重开接收中断
}
以下是主机部份 #include <iom128v.h> #include <macros.h> #define uchar unsigned char #define uint unsigned int #include "delay.h" #include "lcd.h" void port_init(void); //SPI initialize // clock rate: 1843199hz void spi_init(void) { SPCR = 0x74; //setup SPI
init_devices(); LCD1602_initial(); LCD1602_sendbyte(iDat,1+0x30 ); // while(1) //{ for(i=0;i<2;i++) {
ATmega128中断设计
A VR的中断源比较多,尤其是ATmega128,一共有35个外部以及内部中断源。
通常情况下,Flash程序存储器空间的最低位置(0x0000-0x0045)定义为复位和中断向量空间。
完整的中断向量见第二章表2-23。
在中断向量表中,处于低地址的中断向量所对应的中断拥有高优先级,所以,系统复位RESET拥有最高优先级。
A.中断设计注意点:1.具备Bootloader功能的A VR,其中断向量区可以在Flash程序存储器空间最低位置和Bootloader区的头部来回迁移,这主要用于配合Bootloader程序的应用。
如果不使用Bootloader功能,一般不要中断向量区进行迁移。
2.Flash较小的A VR芯片,其一个中断向量占据1个字的空间,用于放置一条相对转移RJMP指令(范围-2K~+2K字),跳到中断服务程序。
对于不使用的中断,在中断向量区中应放置1条中断返回指令RETI,增强程序的抗干扰性。
3.ATmega128的Flash空间为64K字节,因此它的一个中断向量占据2个字的空间,用于放置一条绝对转移JMP指令(指令长度为2个字),跳到中断服务程序。
对于不使用的中断,在中断向量区中应连续放置2条中断返回指令RETI,增强程序的抗干扰性。
当使用汇编语言编写系统程序时应注意。
4.当MCU响应一个中断时,其硬件系统会自动中断返回地址压入系统堆栈,并将关闭全局中断响应(硬件将中断标志I位清0),清除该中断的中断标志位;执行中断返回指令RETI时,硬件会先允许全局中断响应(硬件将中断标志I位置1),然后从系统堆栈中弹出返回地址到PC程序计数器中,继续执行被中断打断的程序。
除此之外,MCU的硬件没有对中断保护做其他处理。
5.因此,用户在编写中断服务程序时,首先要编写中断现场保护程序,如保护MCU的状态寄存器等。
在中断返回之前,不要忘记恢复中断现场。
6.如果设置和允许外部中断响应,即使是外部INT0..7引脚设置为输出方式,在引脚上的电平变化也会触发外部中断的发生,这一特性提供了使用软件产生中断的途径。
atmega128实用双串口通讯
}
tx_data[21] =data;
led_2_0();
//----------------数据校验、处理部分
if( (tx_data[0]==0xfe) && (tx_data[21]==0x16) )
{
//--------------------------略 }
} //--------uart 1----RX-----中断方式- 同上---------------------ISR(USART1_RX_vect) {
unsigned char status,data; status=UCSR1A; data=UDR1; unsigned char f; //----status &= ~(FRAMING_ERROR1 | PARITY_ERROR1 | DATA_OVERRUN1); //----f=data;
//---------------------------------------------
#define
led_1_1() (PORTE |= bit(3))//--1
#define #define #define #define #define #define #define #define #define
Atmega128 实用串口通讯程序
1、 双串口异步通讯, USART0——发送使能,接收使能 、2400bps/8 位/偶校验/1 停止位
USART1——发送使能、9600bps/8 位/无校验/1 停止位
2、 外围 5 个 LED 指示 共阳极, PE3~PE7
#include <avr/io.h> #include <util/delay.h> #include <stdio.h> #include <avr/interrupt.h> #include <avr/wdt.h>
AVR ATmega128全功能工业控制器设计文档说明书
AVR单片机的全功能工业控制器设计吴焕琅深圳市中天越华自动控制科技有限公司摘要:介绍一款工业级的实用全功能控制器。
该控制器能隔离采集多种输入信号,输出多种控制信号;具有实时时钟、历史数据存储功能,彩色液晶显示界面,带有触摸屏操作和远程通信接口。
核心部分CPU采用AVR ATmega128单片机。
目前已用于批量生产。
关键词:隔离采集控制单片机彩色显示485接口ATmega128DS1642引言在自动控制产品的设计过程中,实现方案的选择常常是很矛盾的。
使用可编程逻辑控制器(PLC)和人机界面(HMI)来实现,开发速度较快,但成本太高,所开发的产品没有市场竞争力;使用单片机开发,成本低但开发周期长、开发量大且通用性不好。
用户需要的是一种成本低、开发周期较短、通用性较好的控制器,因此全功能工业控制器有很大的应用市场。
全功能工业控制器的整个电路分为信号隔离输入部分、控制器输出部分、实时时钟与历史数据存储部分、彩色液晶显示和触摸屏控制部分、通信接口等。
1信号隔离输入电路信号隔离输入电路分为开关量隔离输入、模拟量隔离输入、高速电脉冲隔离输入,电路如图1所示,开关量的隔离输入较为简单,输入信号采用光耦进行隔离后送入单片的普通I/O,单片机用查询方式进行采集。
图1信号隔离输入电路高速电脉冲的采集需要注意的是,所设计的电路必须适应高速信号采集的要求,因此隔离光耦应采用高速光耦(如6N137等)。
采用查询方式采集高速脉冲容易造成采集数据的丢失,高速脉冲应采用中断方式进行采集。
模拟量隔离采集是本控制器的一个重点和难点,笔者之前采用了线性光耦等多种方式进行模拟量的隔离采集实验,均未获满意的效果。
这里采用一种先将模拟量数字化(使用AD7705),然后通过有光耦隔离的数据口送到CPU进行模拟量隔离采集的方式,效果理想。
2控制器输出电路控制器的输出方式有继电器输出、晶体管输出、模拟电压输出,如图2所示。
继电器输出和晶体管输出电路较为简单,这里不作详细的介绍。
Almel ATmega128 ATmega128L 可编程 Flash 说明书
产品特点•高性能、低功耗的 AVR® 8位微处理器•先进的 RISC 结构–133条指令 – 大多数可以在一个时钟周期内完成–32 x 8 通用工作寄存器 + 外设控制寄存器–全静态工作–工作于16 MHz时性能高达16 MIPS–只需两个时钟周期的硬件乘法器•非易失性的程序和数据存储器–128K 字节的系统内可编程Flash寿命: 10,000次写/擦除周期–具有独立锁定位、可选择的启动代码区通过片内的启动程序实现系统内编程真正的读-修改-写操作–4K字节的EEPROM寿命: 100,000次写/擦除周期–4K 字节的内部SRAM–多达64K字节的优化的外部存储器空间–可以对锁定位进行编程以实现软件加密–可以通过SPI实现系统内编程•JTAG接口(与IEEE 1149.1标准兼容)–遵循JTAG标准的边界扫描功能–支持扩展的片内调试–通过JTAG接口实现对Flash, EEPROM, 熔丝位和锁定位的编程•外设特点–两个具有独立的预分频器和比较器功能的8位定时器/计数器–两个具有预分频器、比较功能和捕捉功能的16位定时器/计数器–具有独立预分频器的实时时钟计数器–两路8位PWM–6路分辨率可编程(2到16位)的PWM–输出比较调制器–8路10位ADC8个单端通道7个差分通道2个具有可编程增益(1x, 10x, 或200x)的差分通道–面向字节的两线接口–两个可编程的串行USART–可工作于主机/从机模式的SPI串行接口–具有独立片内振荡器的可编程看门狗定时器–片内模拟比较器•特殊的处理器特点–上电复位以及可编程的掉电检测–片内经过标定的RC振荡器–片内/片外中断源–6种睡眠模式: 空闲模式、ADC噪声抑制模式、省电模式、掉电模式、Standby模式以及扩展的Standby模式–可以通过软件进行选择的时钟频率–通过熔丝位可以选择ATmega103兼容模式–全局上拉禁止功能•I/O和封装–53个可编程I/O口线–64引脚TQFP与 64引脚 MLF封装•工作电压–2.7 - 5.5V ATmega128L–4.5 - 5.5V ATmega128•速度等级–0 - 8 MHz ATmega128L–0 - 16 MHz ATmega128微处理器,具有128K字节的系统BDTIC /ATMEL2ATmega1282467L–AVR–05/04引脚配置Figure 1. ATmega128的引脚综述ATmega128为基于AVR RISC 结构的8位低功耗CMOS 微处理器。
ATmega128 ATmega128L 介绍
ATmega128 ATmega128L 介绍
ATmega128/128L 带 128K 字节 FLASH 的在线可编程 8 位微控制 器 是 AVR 系列中功能最强的单片机,掌握了 ATmega128 的开发应用, 对其它 AVR 单片机的开发应用等于杀鸡用牛刀,快极了 1 特 点
ATmega128 具有一整套的编程和系统开发工具 C编译器 宏汇编器 调试/模拟器 JTAG ICE 在线仿真器和SL-MEGA128评估板 二 ATmega103 和 ATmega128 的兼容性
ATmega128 是一种很复杂的微控制器 它的 I/O 地址取代了保留在AVR指令集中的 64 个 I/O地 址 为确保向后兼容 ATmega103 ATmega103上所有I/O的位置与ATmega128上的相同 很多附加的 I/O 地址被加到一个从$60到$FF的扩展外部I/O空间中(例如 在ATmega103 的内部 RAM 空间中) 这些地址只能用 LD/LDS/LDD 和 ST/STS/STD 指令访问 而不能用 IN 和 OUT 指令 内部 RAM 空 间的重定位对于ATmega103用户来说可能仍是一个问题 同样 如果代码使用绝对地址那么增加的中 断向量也是一个问题 要解决这些问题 可以通过编程一个熔丝M103C来选择 ATmega103 兼容模式 在这一模式下 不能使用扩展I/O空间中的程序 所以内部 RAM象ATmega103一样定位 同时 扩展 中断向量被去除 ATmega128 百分之百与 ATmega103引脚兼容 在PCB上可以替代ATmega103 应用笔记 “用ATmega128 替换 ATmega103” 中说明了用户在用ATmega128 替换 ATmega103时应 注意的事项 三 ATmega103 兼容模式
AVR ATMEGA128 串口简单好使程序
//以上是串口发送接收函数
int main(void)
{
//PORTE=0B01000011;//调整让单片机的发送和接收直接连到MAX3232上
//DDRE =0B11100110;
PORTE=0B01110011;//针对本电路中的相关设置RS485通信
DDRE =0B11110110;
unsigned char temp;
Usart0_init();
while(1)
{
temp=Usart0_receive();
Usart0_transmit(temp);
//Usart0_transmit(0x5f);
}
//return 0;
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include<util/delay.h>
#define UDRE0 5
#define RXC0 7
void Usart0_init(void) ;
//设置波特率9.6k,8位数据位,无校验,接收发送使能,1位停止位
UCSR0B=(1<<RXEN0)|(1<<TXEN0); //发送接收使能,使用查询方式,故没有使能中断
}
void Usart0_transmit(unsigned char c) //查询方式发送接收字符函数
{
while( !(UCSR0A&(1<<UDRE0)));//等待发送缓冲区为空
UDR0=c;
void Usart0_transmit(unsigned char c);
