atmega128芯片 avr studio 编写程序 要求:(1)使用 USART0 进行通信。要求帧结构为无奇偶校验位,1 位停止位,字符长度 8 位。 通信波特率 9600。 (2)通信间隔为 1s,即每秒发送一次时间信息。要求该 1s 间隔由定时器中断产生。 (4)设8个独立按键K1~K8分别表示数字1~8。按下任1按键,则将其按键值经TXD0发出。 RXD0收到按键值数据后,则将该数据显示到4位数码管个位,同时数码管原显示内容向左 滚动1位。
时间: 2023-11-22 20:56:05 浏览: 229
以下是使用 AVR Studio 7 编写的程序:
```c
#include <avr/io.h>
#include <avr/interrupt.h>
// 定义波特率和定时器中断频率
#define BAUD_RATE 9600
#define TIMER_FREQ 1
// 定义数码管引脚
#define SegA PB0
#define SegB PB1
#define SegC PB2
#define SegD PB3
// 定义按键引脚
#define K1 PD0
#define K2 PD1
#define K3 PD2
#define K4 PD3
#define K5 PD4
#define K6 PD5
#define K7 PD6
#define K8 PD7
// 定义全局变量
volatile uint8_t key_value = 0;
volatile uint8_t disp_value = 0;
volatile uint32_t timer_count = 0;
// 初始化 USART0
void USART0_Init(void) {
// 设置波特率
UBRR0H = (F_CPU / 16 / BAUD_RATE - 1) >> 8;
UBRR0L = (F_CPU / 16 / BAUD_RATE - 1);
// 启用接收和发送
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
// 设置帧格式:8个数据位,无奇偶校验位,1个停止位
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
// 初始化定时器1
void Timer1_Init(void) {
// 设置计数器模式为CTC模式
TCCR1B |= (1 << WGM12);
// 计算计数器所需的预分频值
uint16_t prescaler = (F_CPU / 256 / TIMER_FREQ) - 1;
// 设置预分频值
OCR1AH = (prescaler >> 8) & 0xFF;
OCR1AL = prescaler & 0xFF;
// 启用定时器1中断
TIMSK1 |= (1 << OCIE1A);
}
// 初始化 IO 引脚
void IO_Init(void) {
// 设置数码管引脚为输出
DDRB |= (1 << SegA) | (1 << SegB) | (1 << SegC) | (1 << SegD);
// 设置按键引脚为输入
DDRD &= ~(1 << K1) & ~(1 << K2) & ~(1 << K3) & ~(1 << K4) & ~(1 << K5) & ~(1 << K6) & ~(1 << K7) & ~(1 << K8);
// 启用按键引脚上拉电阻
PORTD |= (1 << K1) | (1 << K2) | (1 << K3) | (1 << K4) | (1 << K5) | (1 << K6) | (1 << K7) | (1 << K8);
}
// 显示数码管内容
void Display(uint8_t val) {
// 选择要显示的数字
switch (val) {
case 0:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegC) | (1 << SegD);
break;
case 1:
PORTB = (1 << SegB) | (1 << SegC);
break;
case 2:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegD) | (1 << SegE) | (1 << SegG);
break;
case 3:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegC) | (1 << SegD) | (1 << SegG);
break;
case 4:
PORTB = (1 << SegB) | (1 << SegC) | (1 << SegF) | (1 << SegG);
break;
case 5:
PORTB = (1 << SegA) | (1 << SegC) | (1 << SegD) | (1 << SegF) | (1 << SegG);
break;
case 6:
PORTB = (1 << SegA) | (1 << SegC) | (1 << SegD) | (1 << SegE) | (1 << SegF) | (1 << SegG);
break;
case 7:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegC);
break;
case 8:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegC) | (1 << SegD) | (1 << SegE) | (1 << SegF) | (1 << SegG);
break;
case 9:
PORTB = (1 << SegA) | (1 << SegB) | (1 << SegC) | (1 << SegD) | (1 << SegF) | (1 << SegG);
break;
}
}
// 定时器1中断服务程序
ISR(TIMER1_COMPA_vect) {
// 每秒发送一次时间信息
if (++timer_count >= TIMER_FREQ) {
// 发送按键值
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = key_value + '0';
// 清空计数器值
timer_count = 0;
}
// 滚动数码管显示内容
if (++disp_value > 9) {
disp_value = 0;
}
Display(disp_value);
}
int main(void) {
// 初始化 IO 引脚
IO_Init();
// 初始化 USART0
USART0_Init();
// 初始化定时器1
Timer1_Init();
// 启用全局中断
sei();
while (1) {
// 检测按键值
if (!(PIND & (1 << K1))) {
key_value = 1;
} else if (!(PIND & (1 << K2))) {
key_value = 2;
} else if (!(PIND & (1 << K3))) {
key_value = 3;
} else if (!(PIND & (1 << K4))) {
key_value = 4;
} else if (!(PIND & (1 << K5))) {
key_value = 5;
} else if (!(PIND & (1 << K6))) {
key_value = 6;
} else if (!(PIND & (1 << K7))) {
key_value = 7;
} else if (!(PIND & (1 << K8))) {
key_value = 8;
}
}
}
```
该程序使用 USART0 进行通信,使用定时器1产生1s的定时中断,在主循环中读取按键值,如果有按键被按下,则将其值存储在全局变量 key_value 中,在定时器中断服务程序中发送该值,并将数码管显示内容向左滚动一位。同时,该程序也支持通过串口发送数据到 ATmega128 芯片,发送的数据将在数码管上显示。
阅读全文