单片机c语言难学吗,c语言很差 可以学单片机吗

该程序展示了如何使用STM32微控制器与DS1302实时时钟模块进行交互,实现时间显示,并通过红外遥控器进行时间调整。程序包括初始化、读写DS1302、红外解码和串口通信等功能,同时也涉及到红外码值处理和GPS时间同步到DS1302的过程。
摘要由CSDN通过智能技术生成

啥也别唠了,给你看一下最简单的六位时钟的一部分程序

#include           //为了布线方便用到了P4口,故包含了STC专用的头文件,可以在STC-ISP软件中下载

#define LEDPORT P0

#define uchar unsigned char

#define uint unsigned int

sbit D1=P3^3;

sbit D2=P3^4;

sbit D3=P3^5;

sbit D4=P3^6;

sbit D5=P3^7;

sbit D6=P4^0;

sbit LED1=P2^5;

sbit LED2=P2^6;

sbit CLK =P2^1;

sbit IO   =P2^2;

sbit RST =P2^3;

sbit ACC0=ACC^0;

sbit ACC7=ACC^7;

unsigned char hour,min,sec;                //小时、分钟、秒

bit rev_start,rev_stop;                                   //GPS接收开始、结束标志位

unsigned char code tab[ ]={0xA0,0xBE,0x64,0x2C,0x3A,0x29,0x21,0xBC,0x20,0x28,0xFF};//0-9,灭

unsigned char  buf[10];         //GPS数据接收缓冲

unsigned char  irtime;//红外用全局变量,用于计算2个下降沿之间的时间

bit decode_ok,irok;

static unsigned char ircode[4];

unsigned char irdata[33];

uchar set,temp,dot;

bit flag,test;

uint cnt;

void Timer_Init()

{

TMOD=0x22;

TH0=0x00; //重载值

TL0=0x00; //初始化值

ET0=1;    //开中断

TR0=1;

IT0 = 1;   //指定外部中断0下降沿触发,INT0 (P3.2)

EX0 = 1;   //使能外部中断

TL2 = 0xCD;                //设置定时初值

TH2 = 0xF8;                //设置定时初值

RCAP2L = 0xCD;                //设置定时重载值

RCAP2H = 0xF8;                //设置定时重载值

ET2=1;

TR2=1;

TH1 = 0xFD;                //9600波特率的初值

TL1 = TH1;                //9600波特率的初值

TR1 = 1;

SCON = 0x50;        //使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)

//        ES = 1;

EA=1;

}

void inputbyte(unsigned char ucDa)

{

unsigned char i;

ACC = ucDa;

for(i=8; i>0; i--)

{

IO = ACC0;                   //相当于汇编中的 RRC

CLK = 1;

CLK = 0;

ACC = ACC >> 1;

}

}

unsigned char outputbyte(void)

{

unsigned char i;

for(i=8; i>0; i--)

{

ACC = ACC >>1;                      //相当于汇编中的 RRC

ACC7 = IO;

CLK = 1;

CLK = 0;

}

return(ACC);

}

void write(unsigned char ucAddr, unsigned char ucDa)

{

RST = 0;

CLK = 0;

RST = 1;

inputbyte(ucAddr);                    //地址,命令

inputbyte(ucDa);                      //写1Byte数据

CLK = 1;

RST =0;

}

unsigned char read(unsigned char ucAddr)

{

unsigned char ucDa;

RST = 0;

CLK = 0;

RST = 1;

inputbyte(ucAddr);                    //地址,命令

ucDa = outputbyte();                 //读1Byte数据

CLK = 1;

RST =0;

return(ucDa);

}

void DS1302_init()

{

if(read(0xc1)!=0x82)  //如果1302掉电,写入下面的初始值

{

write(0x8e,0x00);//关闭写保护

write(0x80,0x22); //设置秒

write(0x82,0x22);//设置分钟

write(0x84,0x22); // 小时

write(0x90,0xa5);//涓流充电

write(0xc0,0x82);//掉电标志位

}

}

void decode(void)//红外码值处理函数

{

unsigned char i, j, k;

unsigned char cord,value;

k=1;

for(i=0;i<4;i++)      //处理4个字节

{

for ( j=1; j<=8;  j++) //处理1个字节8位

{

cord=irdata[k];

if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差

{

value=value|0x80;

}

else

{

value=value;

}

if(j<8)

{

value=value>>1;

}

k++;

}

ircode[i]=value;

value=0;

}

if(ircode[2]==~ircode[3])

decode_ok=1;//解码完毕后标志位置1

}

void Display(unsigned char a,b,c)   //数码管显示

{

static unsigned char i;

LEDPORT=0xff;

switch (i)

{

case 0: if(a/16) LEDPORT=tab[a/16]&dot; else LEDPORT=tab[10]&dot;D1=0;D2=D3=D4=D5=D6=1;        break;

case 1: LEDPORT=tab [a%16];   D2=0;D1=D3=D4=D5=D6=1;    break;

case 2: LEDPORT=tab [b/16];            D3=0;D1=D2=D4=D5=D6=1;        break;

case 3: LEDPORT=tab [b%16];        D4=0;D1=D2=D3=D5=D6=1;        break;

case 4: LEDPORT=tab [c/16];            D6=0;D1=D2=D3=D4=D5=1;        break;

case 5: LEDPORT=tab [c%16];    D5=0;D1=D3=D4=D6=D2=1;        break;

}

i++;

if(i==6)i=0;

}

void ir_work()

{

if(ircode[2]==0x1e)

test=!test;

if(ircode[2]==0x05)

{

set++;

if(set==4)

set=0;

}

if(set==1)

{

if(ircode[2]==0x02|ircode[2]==0x06)                                                //hour

{

temp=(read(0x85)/16)*10+read(0x85)%16;

temp++;if(temp==24)temp=0;

write(0x84,(temp/10)*16+temp%10);

}

if(ircode[2]==0x08|ircode[2]==0x04)

{

temp=(read(0x85)/16)*10+read(0x85)%16;

temp--;if(temp==-1)temp=23;

write(0x84,(temp/10)*16+temp%10);

}

}

if(set==2)                                                                         //min

{

if(ircode[2]==0x02|ircode[2]==0x06)

{

temp=(read(0x83)/16)*10+read(0x83)%16;

temp++;if(temp==60)temp=0;

write(0x82,(temp/10)*16+temp%10);

}

if(ircode[2]==0x08|ircode[2]==0x04)

{

temp=(read(0x83)/16)*10+read(0x83)%16;

temp--;if(temp==-1)temp=59;

write(0x82,(temp/10)*16+temp%10);

}

}

if(set==3)                                                                         //sec

{

if(ircode[2]==0x02|ircode[2]==0x06)

{

temp=(read(0x81)/16)*10+read(0x81)%16;

temp++;if(temp==60)temp=0;

write(0x80,(temp/10)*16+temp%10);

}

if(ircode[2]==0x08|ircode[2]==0x04)

{

temp=(read(0x81)/16)*10+read(0x81)%16;

temp--;if(temp==-1)temp=59;

write(0x80,(temp/10)*16+temp%10);

}

}

decode_ok=0;

}

void main()

{

Timer_Init();

DS1302_init();

dot=0xff;

flag=1;

while(1)

{

hour= read(0x85);

min = read(0x83);

sec  = read(0x81);

/*        if((hour==0x08)&&(min==0x00) )                         //可以设置为每天的某个时间打开GPS对一下时间再关掉,这里设置的是8:00

ES=1;

else

ES=0;*/

if(flag==1&&cnt>500)                                  //上电稍做延时再打开串口,防止数码管显示出错

{

flag=0;

cnt=0;

ES=1;

}

if((rev_stop==1)&&(buf[1]=='M')&&(buf[2]=='C')&&(buf[3]==','))//如果接收到GPRMC        就把GPS接收到的时间写入DS1302

{

ES=0;

hour= (buf [4]-0x30)* 16+ buf[5] -0x30;

min=  (buf [6]-0x30)* 16+ buf[7]-0x30;

sec=  (buf[8]-0x30)* 16+ buf[9]-0x30;

hour=  hour / 16 * 10 + hour % 16;

hour= (hour+8) % 24;        //UTC Time换算成北京时间

hour=hour/10*16+hour%10;

write(0x84,hour);

write(0x82,min);

write(0x80,sec);

ES=1;

rev_stop=0;

}

if( sec==  (buf[8]-0x30)* 16+ buf[9]-0x30)                                        //用左上角的小点显示有无GPS信号

dot=0xdf;

else

dot=0xff;

if(irok)                        //如果接收到正确的红外信号后进行红外处理

{

decode();

irok=0;

}

if(decode_ok)                  //如果解码正确就进入调时程序

{

ir_work();

}

if(test)                                                //需要时可以遥控关闭屏幕

{

ET2=0;

P0=0xff;

LED1=LED2=1;

}

else

{

ET2=1;

}

}

}

void int0 (void) interrupt 0 //外部中断0服务函数           用于红外解码

{

static unsigned char  i;             //接收红外信号处理

static bit startflag;                //是否开始处理标志位

if(startflag)

{

if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms

i=0;

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

irtime=0;

i++;

if(i==33)

{

irok=1;

i=0;

}

}

else

{

irtime=0;

startflag=1;

}

}

void timer0 (void) interrupt 1 //定时器0中断服务函数 ,红外解码

{

irtime++; //计算2个下降沿之间的时间

}

void Uart_Receive(void) interrupt 4         //串口中断,用于GPS数据接收

{

unsigned char ch,num;

ES = 0;

if (RI)                                        //如果接收完成则进入

{

ch = SBUF;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值