Atmega16单片机实用程序

合集下载

atmega16单片机c语言程序设计经典实例

atmega16单片机c语言程序设计经典实例

atmega16单片机c语言程序设计经典实例中括号在C语言中用于表示数组、结构体、联合体和枚举类型等的定义和使用。

在ATmega16单片机的C语言程序设计中,我们经常会用到数组和结构体,因此本文将以中括号为主题,详细介绍ATmega16单片机上C语言程序设计的经典实例,包括数组的定义和使用、结构体的定义和使用、联合体的定义和使用以及枚举类型的定义和使用。

一、数组的定义和使用数组是一种用于存储一组相同类型的数据项的集合。

在ATmega16单片机上,我们可以使用数组来存储和操作多个引脚的状态、多个传感器的数据等。

1. 数组的定义在C语言中,可以使用方括号来定义一个数组。

下面是一个例子,定义了一个长度为5的整型数组:int array[5];其中,int表示数组的元素类型,array为数组名,[5]表示数组的长度。

2. 数组的初始化数组可以在定义的同时进行初始化。

例如,可以使用大括号将数组的元素初始化为指定的值。

下面是一个例子,将数组的元素初始化为1、2、3、4、5:int array[5] = {1, 2, 3, 4, 5};3. 数组的访问可以使用下标(在中括号内)来访问数组的元素。

数组的下标从0开始,最大值为数组长度减1。

下面是一个例子,访问数组的第一个元素和最后一个元素:int firstElement = array[0];int lastElement = array[4];可以使用循环结构来遍历数组的所有元素:for (int i = 0; i < 5; i++) {访问数组的第i个元素int element = array[i];其他操作}二、结构体的定义和使用结构体是一种可以存储不同类型数据项的数据结构。

在ATmega16单片机上,结构体可以用于存储和操作多个相关的数据项,比如传感器的位置和数值等。

1. 结构体的定义在C语言中,可以使用关键字struct来定义结构体。

下面是一个例子,定义了一个包含姓名和年龄的结构体:struct Person {char name[20];int age;};其中,Person为结构体名,name和age为结构体的成员。

ATMEGA16读写iic(TWI)(24c02)C语言程序

ATMEGA16读写iic(TWI)(24c02)C语言程序

ATMEGA16 读写iic(24c02) C 语言程序测试通过nclude <iom16v.h>#i nclude "I2C.h"#in clude "1602.h"#in clude "delay.h"/*通过AVR往I IC写数据,并通过串口把数据读出显示出来*///===============================================================void UAR_i nit(void) //UART 初始化{ DDRD = 0x02;PORTD = 0x00;UCSRA = 0x02; /* 无倍速*/UCSRB = 0x18; /*允许接收和发送*/U(SRC= 0x06; 1*8位数据,1位停止位,无校验*/UBRRH = 0x00;UBRRL = 12; /*9600*/}//===============================================================void USART_TXD(float data) // 发送采用查询方式{while( !(UCSRA & BIT(UDRE)));UDR=data;while( !(UCSRA & BIT(TXC )));UCSRA|=BIT(TXC);}void mai n(void){un sig ned char i;// LCDinit();uart_i ni t();//TART 初始化SEI(); // 全局中断使能while(1){/*I2C_Write('n',0x00); I2C_Write('c',0x01); I2C_Write('e',0x02);I2C_Write('p',0x03); I2C_Write('u',0x04);*/ i=I2C_Read(0x00); //LCD_write_char(0,0,i); USART_TXD(i); i=I2C_Read(0x01);//LCD_write_data(i); USART_TXD(i); i=I2C_Read(0x02); //LCD_write_data(i); USART_TXD(i);i=I2C_Read(0x03); //LCD_write_data(i); USART_TXD(i); i=I2C_Read(0x04); //LCD_write_data(i); USART_TXD(i);}}/* 上面上主函数部分*/#include <macros.h>#include "delay.h"//I2C 状态定义//MT 主方式传输MR 主方式接受#define START 0x08#define RE_START 0x10#define MT_SLA_ACK 0x18 #define MT_SLA_NOACK 0x20 #define MT_DATA_ACK 0x28 #defineMT_DATA_NOACK 0x30 #define MR_SLA_ACK 0x40 #define MR_SLA_NOACK 0x48 #define MR_DATA_ACK 0x50 #define MR_DATA_NOACK 0x58#define RD_DEVICE_ADDR 0xA1 // 前4位器件固定,后三位看连线,最后1位是读写指令位#define WD_DEVICE_ADDR 0xA0//常用TWI操作(主模式写和读)#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) // 启动I2C #define Stop()(TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) // 停止I2C #define Wait() {while(!(TWCR&(1<<TWINT)));} // 等待中断发生#define TestAck() (TWSR&0xf8) // 观察返回状态#define SetAck (TWCR|=(1<<TWEA)) // 做出ACK应答#define SetNoAck (TWCR&=~(1<<TWEA)) // 做出Not Ack 应答#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) // 启动I2C#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} // 写数据到TWDRunsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress); unsigned charI2C_Read(unsigned RegAddress);/*********************************************I2C 总线写一个字节返回0: 写成功返回1: 写失败**********************************************/unsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress){Start(); //I2C 启动Wait();if(TestAck()!=START)return 1; //ACKWrite8Bit(WD_DEVICE_ADDR); // 写I2C 从器件地址和写方式Wait(); if(TestAck()!=MT_SLA_ACK) return 1; //ACKWrite8Bit(RegAddress); // 写器件相应寄存器地址Wait();if(TestAck()!=MT_DATA_ACK)return 1; //ACKWrite8Bit(Wdata); // 写数据到器件相应寄存器Wait();if(TestAck()!=MT_DATA_ACK)return 1; //ACKStop(); //I2C 停止delay_nms(10); // 延时return 0;}/*********************************************I2C 总线读一个字节返回0: 读成功返回1: 读失败**********************************************/unsigned char I2C_Read(unsigned RegAddress){ unsigned char temp;Start();//I2C 启动Wait();if (TestAck()!=START) return 1; //ACKWrite8Bit(WD_DEVICE_ADDR); // 写I2C 从器件地址和写方式Wait(); if (TestAck()!=MT_SLA_ACK) return 1; //ACKWrite8Bit(RegAddress); // 写器件相应寄存器地址Wait();if (TestAck()!=MT_DATA_ACK) return 1;Start(); //I2C 重新启动Wait();if (TestAck()!=RE_START) return 1;Write8Bit(RD_DEVICE_ADDR); // 写I2C 从器件地址和读方式Wait(); if(TestAck()!=MR_SLA_ACK)return 1; //ACKTwi(); // 启动主I2C 读方式Wait(); if(TestAck()!=MR_DATA_NOACK) return 1; //ACKtemp=TWDR;// 读取I2C 接收数据Stop();//l2C 停止return temp;}/*以上是IlC.h头文件部分,需要对照技术文档好好研究*/延时函数编译器:I CC-AVR V6.31A 日期:2005-11-24 20:29:57 目标芯片:M16 时钟:8.0000M Hz作者:arche ng504------------------------------------------------- */#ifndef __delay_h#defi ne __delay_hvoid delay_ nus(un sig ned int n);void delay_ nms(un sig ned int n);void delay_1us(void);void delay_1ms(void);void delay_1us(void) //1us 延时函数{asm( "n op");}void delay_ nus(un sig ned int n) 〃N us 延时函数{un sig ned in t i=0;for (i=0;i <n ;i++)delay_1us();}void delay_1ms(void) //1ms 延时函数{un sig ned in t i;for (i=0;i<1140;i++);}void delay_ nms(un sig ned int n) //N ms 延时函数{un sig ned in t i=0;for (i=0;i <n ;i++)delay_1ms();}#en dif/*以上是delay.h 部分,再加上IIC中自带的iom16v.h和macros.h就可以编译通过*//*注意点:本程序在实验板ATMEGA1上测试通过,在示波器把SCL, SDA信号线有数据,移值到自己电路上可以放心使用,在ATMEGA3上一样使用,本人24C02的A2, A1, A0都是接地,若地址不一样,在程序相应位置改一下就可以,串口上调试单片机的基础,所以它一定要会用*//*本程序调试软件环境是ICC6.31*/。

单片机atmege16控制可控硅调光电路与部分程序

单片机atmege16控制可控硅调光电路与部分程序

单片机控制可控硅调光不闪电路单片机控制可控硅调光,是件比较麻烦的事情,开始是没加过零检测,结果不管怎么做pwm 频率多高,都很闪,用了下面这个后就不闪了.在51hei单片机开发板上测试成功。

要调光的话,moc3063是不行的,3063是过零导通的,对交流电源的控制结果只能是对半波,而不能斩波,通常要调光,调压的话用3052,配合交流过零信号硬件,也可用变压器+二极管做过零检测电路.过零信号边沿触发中断,在过零后延时输出控制信号给光藕,使可控硅导通,过零前边沿关闭控制信号,使可控硅自然关断,完成一个半波的斩波控制,调整延时值就可以调节输出电压了,当然,延时值根据电源频率及定时器分频比不同,有相应的取值范围,一般可以用外中断负责过零边沿触发,一个边沿(至于哪个边沿与过零信号硬件结构有关)负责关闭可控硅,一个边沿负责延时计算,并写入定时器,由定时器中断来打开可控硅.'改变INT1中断中的"移相值",即可改变输出电压,这里T2分频比为1024,可根据主频计算出移相值取值范围'程序采用电平触发,脉冲触发可作相应修改'若主频12M,电源50Hz,则移相值计算约为0--117,但实际使用0-105就可以了,太大了会移相到过零位置,使可控硅不能关断'单片机类型atmege16,开发者: email:372xcom1@ 下面是主要的程序'主程序:'略ldi r16,4 'INT1上升,下降沿都中断Out Mcucr,R16ldi r16,128 'INT1中断允许,INT0,INT2中断禁止Out Gicr,R16ldi r16,7Out Tccr2,R16 'T2开始循环计数andi r17,127 '暂时禁止T2比较匹配中断(T2比较匹配中断在中断程序中启闭) Out Timsk,R17sei'-------------------------中断服务程序------------------------------------------Int_comp2: '移相中断push r17in r17,sregpush r17cbi porta,5 '触发信号输出in r17,timskandi r17,127 '禁止T2比较匹配中断out timsk,r17pop r17out sreg,r17pop r17retiInt1_isr: '电源同步中断push r17in r17,sregpush r17sbis pind,3 'int1引脚(电源同步)状态=1则跳行,上升沿中断rjmp falling'上升沿中断sbi portA,5 '关触发rjmp isr_overFalling:'下降沿中断ldi r17,0Out Tcnt2,R17 'T2清零lds r17,移相值Out Ocr2,R17'清中断标志,确保中断正确执行in r17,tifrori r17,128 '清T2匹配标志Out Tifr,R17in r17,timskori r17,128Out Timsk,R17 '允许T2比较匹配中断Isr_over:pop r17pop r17Reti上面的是的是A VR的汇编程序,51的也可以实现的,就是用定时器的溢出中断啦,溢出值-移相值=初始值触发可控硅用脉冲方式,计算好触发脉冲宽度对应的计数初值同步信号输入--下沿中断写计数初值,开始计数--计数器溢出中断,判标志=0,打开可控硅,写触发脉冲初值,写标志=1---再次溢出中断,判标志=1,关可控硅,清零标志--------再次同步中断超低成本的可控硅开关控制器概述传统的机械恒温器主要用于厨具等开关器具,控制温度的开关调节,存在调节精度不高、低温调节不精确、出厂校准、容易损坏零部件等缺陷,本文利用PIC10F204微控制器,结合可控硅开关器件设计的基于微控制器的恒温器,可广泛应用台灯、吸尘器等家用器具,具有超低成本、操作简单、灵敏度高、自动断电等功能。

ATmega16串口程序-值得参考

ATmega16串口程序-值得参考

// USART Transmitter buffer
#define TX_BUFFER_SIZE 16
volatile char tx_buffer[TX_BUFFER_SIZE];
volatile unsigned char tx_wr_index,tx_rd_index,tx_counter;
if (++rx_wr_index == RX_BUFFER_SIZE) //写指针指向下一个单元,并判断是否到了队列的尾部,(不表示接受缓冲区是否满!)
rx_wr_index=0; //到了尾部,则指向头部(构成环状)
if (++rx_counter == RX_BUFFER_SIZE) //队列中收到字符加1,并判断是否队列已满
{
rx_counter=0; // 队列满了,队列中收到字符个数为0,表示队列中所有以前的数据作废,因为最后的数据已经把最前边的数据覆盖了
rx_buffer_overflow=1; //置缓冲区溢出标志。在主程序中必要的地方需要判断该标志,以证明读到数据的完整性
put_s("Hello!");
put_s("这是一个简单的高速的串口驱动程序");
put_s("请你输入任意的字符,单片机将返回你输入的字符");
while (1)
{
put_c(get_c());
}
}
//Makefile,主要的几项,只是针对我这里的程序,要灵活运用哦
//usart.h
//常量定义
#define BAUDRATE 9600 //波特率
//#define F_CPU 4000000 //晶振频率4.0MHz

单片机片上开发方法(ATmega16为例)

单片机片上开发方法(ATmega16为例)

在开始之前

设置ICC,使其配置成为可以开发ATmega16 的编译器环境
2014-11-12
43
设置你的ICC

Project Options…
2014-11-12
44
设置你的ICC

如图在Target标签中的Device Configuration里 选择ATmega16单片机,点击OK即可
2014-11-12
35
2014-11-12
36
在工程中建立一个LED.c文件

File Save As…
2014-11-12
37
在工程中建立一个LED.c文件

在刚建立的LED_test文件夹内保存成LED.c
2014-11-12
38
将LED.c添加到工程中

File (右击)Add File(s)…
LED灯闪烁程序解释
/*8MHz晶振下*/ //微秒级延时函数 void delay_us(unsigned int time) {do { time--; } while (time>1);} //毫秒级延时函数 void delay_ms(unsigned int time) {while(time!=0) { delay_us(1000); time--;}}
以后,我们可以 通过双击这个文 件运行ICC,可 不受其30天试用 期限制,但仅限 于自己学习,不 能用于其它用途!
2014-11-12
28
运行ICC

使用刚才的ICC.exe运行ICC7.13
2014-11-12
29
ICC的界面
2014-11-12
30
新建一个工程

基于AVR单片机--Atmega16的串口通信使用

基于AVR单片机--Atmega16的串口通信使用

基于AVR单片机--Atmega16的串口通信使用//以下程序经验正可以用,MCU:M16,晶振:8M,直接用USB转串口线上的公头(针头),//第2针(RXD)接M16上的PD1口(15脚TXD),第3针(TXD)接M16上的PD0口(14脚RXD),//第5针接地,此时若板上有MAX232,则需把MAX232芯片去掉,这样才能正常工作#include<avr/io.h>#include<avr/interrupt.h>#define uchar unsigned char#define uint unsigned int#define fosc 8000000//晶振频率#define BAUD 9600 //波特率void USART_send(uchar date)//发送一个字节{while(!(UCSRA&(1<<UDRE)));//等待USART数据寄存器为空,UDRE为1说明缓冲器为空,已准备好进行数据接收或发送UDR=date;//发送数据}void init(){DDRB=0xff;//设置PB口为输出PORTB&=~(_BV(PB4)|_BV(PB5)|_BV(PB6)|_BV(PB7));//让高4位的LED灭//波特率寄存器设置UBRRH=(fosc/BAUD/16-1)/256;UBRRL=(fosc/BAUD/16-1)%256;//UCSRB|=_BV(RXEN)|_BV(TXEN)|_BV(RXCIE);UCSRB|=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);//使能发送,接收,接收完成中断sei();//开全局中断}int main(){init();USART_send('d');//发送数据'd'while(1);}volatile char date1;SIGNAL(SIG_UART_RECV){date1=UDR;//接收数据PORTB=date1;}。

ATMAGE16内部ADC的使用程序

ATMAGE16内部ADC的使用程序

ATMAGE16内部ADC的使用程序程序说明:本例程是控制ATMAGE16内部的AD进行转换,然后将转换结果转换成电压,显示到数码管上。

本人刚开始用A VR这是写的第一个程序,可能思路上会有很多问题,忘个位网友看后指出,我的邮箱是462511238@欢迎和我交流。

写这个程序的目的是为了用AD采集一个模拟量,在网上看了些历程,很多都是用查询发写的。

就是启动ADC转换以后,等待ADC转换完成,然后就将数据读出,显示出来。

这种程序也就只能自己玩玩,毫无实用价值。

因为在实际产品中,会有很多干扰信号,采集一次就显示,得到的数据往往是干扰信号。

要消除这些干扰,需要在ADC的输入通道上加上滤波电容,当然更重要的是在程序中进行处理。

这也就是所谓的数字滤波了,由于单片机运算能力有限,很多PC上的一些算法对于单片机来说就过于复杂了。

我在这个程序中,只是采用多次采集数据,然后求平均值的算法进行最简单的滤波的,但这在要求不高的场合已经能够满足要求了。

采用查询法,一直查询ADC是否转换结束是非常浪费CPU时间的。

因此我们需要开启ADC的中断,但是每隔多久进行一次转换呢,一直都不停的转换,其实对我们得到准确的数据意义不大,(我采集的是桥式应变片经过差分放大的信号)。

并且数据刷新太快,用于显示,会给人不稳定的感觉,还没看清楚显示的是什么,就又刷新了。

由于A VR的ADC可以用定时的溢出来触发转换。

于是我想到,用定时器来定时,每隔0.1S采集一次,1S 刷新一次显示,也就是每次显示的数据是采集十次数据的平均值,这样做出来还是比较稳定的。

程序实现思路:将ATMAGE16的定时器1设置为普通计数模式,并且将时钟256分频作为定时器1的工作脉冲(我采用的是4MHZ晶振)。

然后将ADC设置为定时器1溢出触发,当定时器溢出后,将触发ADC转换,ADC转换完成后,进入ADC中断,读取数据,并对定时器进行重装初值。

这样,就可以保证,每次进行ADC转换的间隔时间基本是一样的。

AVR ATmega16中文说明书

AVR  ATmega16中文说明书

ALU- 算术逻辑单元AVR ALU 与32 个通用工作寄存器(R0-R31)直接相连。

寄存器与寄存器之间、寄存器与立即数之间的ALU 运算只需要一个时钟周期。

ALU 操作分为3 类:算术、逻辑和位操作。

此外还提供了支持无/ 有符号数和分数乘法的乘法器。

具体请参见指令集。

状态寄存器状态寄存器包含了最近执行的算术指令的结果信息。

这些信息可以用来改变程序流程以实现条件操作。

如指令集所述,所有ALU 运算都将影响状态寄存器的内容。

这样,在许多情况下就不需要专门的比较指令了,从而使系统运行更快速,代码效率更高。

在进入中断服务程序时状态寄存器不会自动保存,中断返回时也不会自动恢复。

这些工作需要软件来处理。

AVR 中断寄存器SREG 定义如下:•Bit 7 –I: 全局中断使能I 置位时使能全局中断。

单独的中断使能由其他独立的控制寄存器控制。

如果I 清零,则不论单独中断标志置位与否,都不会产生中断。

任意一个中断发生后I 清零,而执行RETI指令后I 恢复置位以使能中断。

I 也可以通过SEI 和CLI 指令来置位和清零。

•Bit 6 –T: 位拷贝存储位拷贝指令BLD 和BST 利用T 作为目的或源地址。

BST 把寄存器的某一位拷贝到T,而BLD 把T 拷贝到寄存器的某一位。

•Bit 5 –H: 半进位标志半进位标志H 表示算术操作发生了半进位。

此标志对于BCD 运算非常有用。

详见指令集的说明。

•Bit 4 –S: 符号位, S = N ⊕VS 为负数标志N 与2 的补码溢出标志V 的异或。

详见指令集的说明。

•Bit 3 –V: 2 的补码溢出标志支持2 的补码运算。

详见指令集的说明。

•Bit 2 –N: 负数标志表明算术或逻辑操作结果为负。

详见指令集的说明。

• Bit 1 – Z: 零标志表明算术或逻辑操作结果为零。

详见指令集的说明。

• Bit 0 – C: 进位标志表明算术或逻辑操作发生了进位。

详见指令集的说明使用CLI 指令来禁止中断时,中断禁止立即生效。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{ for(y_address=y1;y_address
#define uint unsigned int #define SET_1(a,b) a|=bit(b) //將寄存器 a 的第 b 位置 1 #define CLR_0(a,b) a&=~bit(b) //將寄存器 a 的第 b 位清 0 #program date code:
const date[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0 X80,//共陽數據;
Atmega16 单片机实用程序
/************************************************ *********************
MCU: ATmega16 外部晶振: 8MHz 程序功能: 4*4 鍵盤識別,LED 七段數碼管顯示,密 碼功能模塊,直流電機正反轉控制
void delayms(int ms) { int i,j;
for(i=ms;i>0;i--) { for(j=1722;j>0;j 1722; }
/************************************************ ******************* 名稱:us 延時子程序 功能:延時指定的 us ************************************************* *******************/ void delayus(uchar us)
//interrupt process program void process()
{ int adcode=0; ADCSRA&=~BIT(ADIE); adcode=ADCL; adcode=(ADCH>3; y_address=y;
LCD_write_data(x_address,y_address,data|(1>3)-1;x _address++)
AD 轉換模塊, 模擬比較器,外部中斷應用,12864 液 晶,C/T0
硬件設計: 參考 PROTUES 硬件仿真電路 調試: 所有程序主要功能都軟硬件仿真通過,實際 使用時要根據需要加入可靠性。 編譯環境: ICC AVR Design by: wdw
************************************************* *******************/ #include #include #include #define uchar unsigned char
0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; #program duan code:
const duan[]={0x20,0x10,0x08,0x04,0x02,0x01}; //段選; char adchannel; int dispbuf[]={0,0,0,0,0,0,}; //顯示緩存; uchar securbuf[]={0,0,0,0,0,}; //5 位密碼緩存; /************************************************ ******************** 名稱:ms 延時子函數 功能:延時指定的 ms ************************************************* ********************/
{
for(us;us0;count--) { adaver=ad_conv(); adaver+=adaver; delayms(1);
} adaver=adaver/8; delayms(1); return adaver; } /************************************************ ********* 名稱:AD 採樣 功能:採樣 AD0 的電壓,內部 2.56V 參考電壓,中斷工作 方式 ************************************************* *********/ void ad0_init() { ADMUX=0xc0; adchannel=0; ADCSRA=0x98; DDRA&=~BIT(0); PORTA&=~BIT(0); SEI(); } #pragma interrupt_handler process:15
相关文档
最新文档