已知晶振是11.0592MHz,波特率为4800,要求串口工作在方式1。
编写程序让串口每秒向外发送一次数据0x55,延时程序直接调用delay():
#include <reg52.h>
void delay()
{
int i, j;
for(i = 0; i < 1000; i++)
for(j = 0; j < 1000; j++);
}
void main()
{
while(1)
{
SBUF = 0x55;
while(!TI);
TI = 0;
delay();
}
}
编写程序让串口每秒向外发送一次数据0x55,延时程序使用定时器产生:
#include <reg52.h>
void timer_init()
{
TMOD = 0x01;
TH0 = (65536 - 11.0592 * 1000 / 12) / 256;
TL0 = (65536 - 11.0592 * 1000 / 12) % 256;
ET0 = 1;
TR0 = 1;
}
void timer0() interrupt 1
{
TH0 = (65536 - 11.0592 * 1000 / 12) / 256;
TL0 = (65536 - 11.0592 * 1000 / 12) % 256;
SBUF = 0x55;
while(!TI);
TI = 0;
}
void main()
{
timer_init();
while(1);
}
每次外部中断0时通过串口发送外部中断0产生的中断次数:
#include <reg52.h>
unsigned char count = 0;
void ext0() interrupt 0
{
count++;
SBUF = count;
while(!TI);
TI = 0;
}
void main()
{
EA = 1;
EX0 = 1;
IT0 = 1;
while(1);
}
编写程序当串口接收到数据后把接收到的数据通过串口再发送出去,同时把接收到的数据取反后送给P2口:
#include <reg52.h>
#include <intrins.h>
sbit P2 = 0xA0;
void Uart_Init()
{
SCON = 0x50; //设置串口工作方式1,波特率4800
TMOD = 0x20; //设置T1为8位自动重装模式
TH1 = 0xFD; //设置波特率
TL1 = 0xFD;
TR1 = 1; //启动T1
ES = 1; //打开串口中断开关
}
void Uart_Send(unsigned char dat)
{
SBUF = dat; //数据发送到SBUF缓冲区
while (!TI); //等待发送完毕
TI = 0; //清空发送标志位
}
void Uart_ISR() interrupt 4 //串口中断
{
if (RI) //接收到数据
{
RI = 0; //清除接收标志位
unsigned char dat = SBUF; //读取接收到的数据
Uart_Send(dat); //发送接收到的数据
P2 = ~dat; //取反后送给P2口
}
}
void main()
{
Uart_Init(); //初始化串口
while (1); //程序不停止
}
2.已知4位8段共阴极数码管的数据口连接了P1口,位选口连接了P2口,当输出低电平时该位被选中,上电后数码管显示数据0000-5000循环显示,时间间隔2秒,编写程序每次外部中断1时数码管显示重新由0000开始进行循环显示。
(要求延时2秒程序由T1定时器实现,单片机晶振为6MHZ,动态显示延时10ms调用“delay10ms()”子程序。)
#include <reg52.h>
unsigned char i;
void delay(void) {
unsigned int j;
for (j = 0; j < 60000; j++);
}
void delay10ms(void) {
unsigned int j;
for (j = 0; j < 600; j++);
}
void display(unsigned char num) {
P1 = num;
P2 = 0x01;
delay10ms();
P2 = 0x02;
delay10ms();
P2 = 0x04;
delay10ms();
P2 = 0x08;
delay10ms();
}
void timer1_init(void) {
TMOD = 0x10;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
EA = 1;
ET1 = 1;
}
void timer1_int(void) interrupt 3 {
i++;
display(i % 10);
if (i == 50) {
i = 0;
}
}
void main(void) {
timer1_init();
while (1) {
}
}
1.P1口连接共阴极8段数码管,上电后数码管0·
9循环显示,中间间隔1秒,编写程序第一次外部中断0时数码管全灭(送0xAA)1秒,第二次中断时数码管全亮(送0X55)1秒,每次外部中断0时以此循环。延时程序直接调用
delay()。
#include <reg52.h>
unsigned char i, flag = 0;
void delay(void) {
unsigned int j;
for (j = 0; j < 60000; j++);
}
void display(unsigned char num) {
P1 = num;
P2 = 0x01;
delay();
P2 = 0x02;
delay();
P2 = 0x04;
delay();
P2 = 0x08;
delay();
}
void external_int0(void) interrupt 0 {
if (flag == 0) {
display(0xAA);
flag = 1;
} else {
display(0x55);
flag = 0;
}
}
void main(void) {
EA = 1;
EX0 = 1;
while (1) {
}
}
P1.0、P1.1、P1.2分别连接了红、黄、绿三
个LED灯,低电平亮,编写交通灯程序红灯亮30秒后绿灯亮25秒,然后黄灯再亮3秒,以此循环,要求延时程序通过调用延时1S子程
序“delay1s()”程序实现。
#include <reg51.h>
void delay1s()
{
unsigned int i, j;
for (i = 0; i < 1000; i++)
for (j = 0; j < 125; j++);
}
void main()
{
while (1)
{
P1 = 0x01; // red LED on
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
P1 = 0x04; // green LED on
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
delay1s();
P1 = 0x02; // yellow LED on
delay1s();
delay1s();
delay1s();
}
}
3.已知void Show_R(uchar r1,uchar r2)函数功能
为控制16个LED亮灭,其中参数r1控制低8位
LED亮,r2控制高8位LED亮,高电平亮,低
电平灭,编写程序使得16个LED流水灯循环点
亮,中间延时程序直接调用delay()子程序。
#include<reg51.h>
void Show_R(uchar r1, uchar r2) {
// Code to control the LED lights based on the value of r1 and r2
}
void delay() {
// Code to implement the delay
}
void main() {
uchar i;
while(1) {
for(i=0; i<=255; i++) {
Show_R(i, 255-i);
delay();
}
}
}
这段代码实现了16个LED流水灯的循环点亮,在主程序中,使用for循环枚举i的值从0到255,每次循环都调用Show_R(i, 255-i)函数,第一个参数控制低8位LED亮,第二个参数控制高8位LED灭。最后调用delay()函数实现延时。
4.P1.0-P1.3连接了4个开关,闭合为0,断开为
1,P1.4-P1.7连接了4个LED,低电平亮,编写程序用开关控制相应的LED亮灭。开关闭合时灯亮,断开时灯灭。
#include<reg52.h>
void main()
{
while(1)
{
P1 = 0xff; // 先设定所有LED灯为灭
if(P1 & 0x01 == 0x00)
P1 &= 0xef; // 开关1闭合,LED1亮
if(P1 & 0x02 == 0x00)
P1 &= 0xdf; // 开关2闭合,LED2亮
if(P1 & 0x04 == 0x00)
P1 &= 0xbf; // 开关3闭合,LED3亮
if(P1 & 0x08 == 0x00)
P1 &= 0x7f; // 开关4闭合,LED4亮
}
}
5.已知6位8段共阴极数码管的数据口连接了P1
口,位选口连接了P2口,当输出低电平时该位被选中,编写程序第一次外部中断0时显示123456,第二次外部中断时显示自己学号后6位,以此循环。
#include <reg52.h>
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar num[12]={1,2,3,4,5,6,7,8,9,0,7,8};
uchar flag=0;
void delay(unsigned int t)
{
while(t--);
}
void display(uchar data)
{
P1=data;
P2=0xfe;
delay(500);
P2=0xff;
}
void INT0() interrupt 0
{
flag++;
if(flag>1) flag=0;
}
void main()
{
EA=1;
IT0=1;
while(1)
{
if(flag==0)
{
for(int i=0;i<6;i++)
{
display(table[num[i]]);
delay(1000);
}
}
else
{
for(int i=6;i<12;i++)
{
display(table[num[i]]);
delay(1000);
}
}
}
}
6.P1.0连接了一个按钮,按下为低电平,P1.1
连接了指示灯,低电平亮,编写程序,第一次按动按钮时指示灯亮,第二次按动按钮时指示灯灭,第三次按动时再亮……以此循环。
#include<reg51.h>
sbit button = P1^0; // 定义按钮对应的引脚
sbit led = P1^1; // 定义指示灯对应的引脚
unsigned char flag = 0; // 定义循环标识变量
void main() {
while(1) {
if (button == 0) { // 当按钮按下时
delay(10); // 延时10ms,去抖动
if (button == 0) { // 再次判断,确保按键按下
flag ++; // 标识变量自增
while(!button); // 等待按键抬起
}
}
if (flag % 2 == 1) { // 当标识变量为奇数时
led = 0; // 指示灯亮
} else { // 当标识变量为偶数时
led = 1; // 指示灯灭
}
}
}
注释:
sbit 是定义单片机的一个引脚的宏,可以简化对引脚的操作。
button 和 led 分别表示按钮和指示灯的引脚。
flag 用来记录按键被按下的次数,并用于控制指示灯的状态。
delay 函数是延时函数,用于去抖动。
while(1) 是一个无限循环,程序不断检测按键的状态。
while(!button) 是等待按键抬起的循环,只有当按键抬起时,程序才继续执行。
在每次检测按键时,都要先判断标识
7.已知P1口接了8个LED,高电平灭,低电平
亮,编写流水灯程序,时间间隔1S。(延时
1S子程序直接调用“Delay1000ms()”)。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED0=P1^0;
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit LED3=P1^3;
sbit LED4=P1^4;
sbit LED5=P1^5;
sbit LED6=P1^6;
sbit LED7=P1^7;
void Delay1000ms(){
uint i,j;
for(i=0;i<1000;i++)
for(j=0;j<120;j++);
}
void main(){
while(1){
LED0=0;
Delay1000ms();
LED0=1;
LED1=0;
Delay1000ms();
LED1=1;
LED2=0;
Delay1000ms();
LED2=1;
LED3=0;
Delay1000ms();
LED3=1;
LED4=0;
Delay1000ms();
LED4=1;
LED5=0;
Delay1000ms();
LED5=1;
LED6=0;
Delay1000ms();
LED6=1;
LED7=0;
Delay1000ms();
LED7=1;
}
}
注释:
#include<reg52.h>:包含51单片机的头文件
sbit LED0=P1^0;:定义 LED0 为 P1.0 管脚
void Delay1000ms(){ ... }:定义延时函数,1000ms
while(1){ ... }:循环执行流水灯代码
LEDx=0/1:点亮/熄灭 LEDx
Delay1000ms():调用延时函数
8.已知void Show_R(uchar r1,uchar r2)函数功能
为控制16个LED亮灭,其中参数r1控制低8位LED亮,r2控制高8位LED亮,编写程序使16位LED灯输出循环加1数据,中间延时程序直接调用delay()子程序。
#include<reg52.h>
void delay();
void Show_R(uchar r1,uchar r2);
void main()
{
uchar i;
while(1)
{
for(i=0; i<256; i++)
{
Show_R(i,i); // 函数调用,将i的值传入作为参数
delay(); // 延时
}
}
}
void Show_R(uchar r1, uchar r2)
{
P1 = ~r1; // 控制低8位LED
P2 = ~r2; // 控制高8位LED
}
void delay()
{
uchar i,j;
for(i=0; i<100; i++)
for(j=0; j<100; j++);
}
上述代码是在使用C语言实现16位LED灯输出循环加1数据的程序。在代码中,主函数中定义一个循环,在循环中调用Show_R函数,Show_R函数控制低8位LED和高8位LED的亮灭。在Show_R函数中,P1的值为r1的反码,P2的值为r2的反码,因为高电平为灭,低电平为亮。最后,程序调用delay函数延时一段时间,控制LED灯循环加1数据的速度。