

/**********************************************************************
* 作者:杨志强 EWOODPECKER_CHRIS YANG
* 日期:2017.03.04
* 特点: STM8S003F3P6 测试串口;
* 时钟:内部 16MHz;
38KHz => 26.31 us; (高电平 13.2)
***********************************************************************/
// 头文件 宏定义
#include <iostm8s003f3.h>
#include"stdio.h"
// 声明;常用数据类型定义*************************/
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
// 位定义, 控制信号口;
#define KEY PD_IDR_IDR1 // 按键 KEY 指定到 PA1 ; 输入寄存器; (上拉输入 ) 内部高电平,被动拉低;
#define LED PA_ODR_ODR3 // 指示灯 LED
//#define IR PD_ODR_ODR3 // IR红外遥控 发射;
#define IR PD_ODR_ODR2 // IR红外遥控 发射;
// 数组定义;
unsigned char Table[8]; // 存储 Music 命令码
// 变量定义;
u8 wy[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; // 0000 0001 / 0000 0010 / 0000 0100 / 0000 10000
u16 end_count = 0;
u8 count = 0;
u8 count0 = 0;
u8 user;
//u16 system = 0x00ff;
u16 system = 0x00;
u16 time_cnt = 0;
u8 hc;
/**********************************************************************
* 函数: CLK_Init(void)
* 功能: 时钟设置;配置成 16MHz;
* 输入: 无;
* 输出: 无;
***********************************************************************/
void CLK_Init(void)
{
CLK_CKDIVR = 0x00; // 配置成 16MHz;
}
/**********************************************************************
* 函数: eeprom_write(u8 addr, u8 dat)
* 功能: EEPROM指定地址写入一个数据
* 输入: 无;
* 输出: 无
***********************************************************************/
void eeprom_write(u8 addr, u8 dat)
{
u8 *p;
p = (u8 *)(0x4000+addr);
*p = dat;
while(!(FLASH_IAPSR & 0x04)); //等待写操作成功
}
/**********************************************************************
* 函数: TIM1_Init(unsigned int psc,unsigned int arr) //psc 分频系数 arr 计数值
* 功能: 时钟定义 初始化;
* 输入: 无
* 输出: 无
***********************************************************************/
void Init_TIM1(u16 psc,u16 arr) //psc 分频系数 arr 计数值
{
//1. 配置定时器 工作模式 和系统时钟;
TIM1_CR1 = 0x00;
/*
ARPE_7 = 0; // ( )
CMS_6 = 0; // ( )
CMS_5 = 0; // ( )
DIR_4 = 0; // ( 0:计数器向上计数; 1:计数器向下计数?)
OPM_3 = 0; // ( 0:发生更新事件时,计数器不停止;1: 发生下一次更新事件时(清除 CEN 位,计数器停止; )
URS_2 = 0; // ( )
UDIS_1 = 0; // ( )
CEN_0 = 0; // ( 0: 禁止计数; 关闭计数器, 使用时,再开启;)
*/
//2. 配置定时器 中断;
TIM1_IER = 0x01; // 0000 0001(中断使能寄存器 )允许更行中断
/*
UIE_0 = 1; // (0: 禁止更新中断; 1: 允许更新中断;)
*/
//3. 进行时钟分频;
TIM1_PSCRH = (psc-1)/256; //进行分频值
TIM1_PSCRL = (psc-1)%256;
//4. 设定计数值上限;
TIM1_ARRH = arr/256; // 溢出值 高位;
TIM1_ARRL = arr%256; // 溢出值 低位;
//5. 开始计数;
//TIM1_CR1 |=0x01; //开始计数
}
/**********************************************************************
* 函数: TIM1 中断函数;
* 功能: 时钟计时 中断标志位 清 0 ;
* 输入: 无;
* 输出: 无
打开 时钟 计时,让他一直不停 的 计数;
计数,根据不同 阶段 来设定 不同的参数,以示 区分;
***********************************************************************/
#pragma vector=13
__interrupt void Inter_Timer1_Over(void)
{
//TIM1_SR1 = 0x00; // 中断标志位 清 0
TIM1_SR1_UIF = 0; // 无更新事件 产生;
TIM1_CR1_CEN = 0; // 停止记数;
}
// D 端口 外部 中断函数;
/*********************************
1120us = 0;
2250us = 1;
13500us = start;
< 1050 X
在 1700 为分界点;
1050 < 1120 < 1700 < 2250
#pragma vector = 8
__interrupt void Inter_EXTI3_IR_Handle(void)
{
uchar IR_Time_H;
uchar IR_Time_L;
uint IR_Time; // 记录脉冲的周期长度;
//读数据之前先停止计数器
TIM2_CR1_CEN=0;
//读计数器的值 TIMx_CNTRH/TIMx_CNTRL
IR_Time_H=TIM2_CNTRH;
IR_Time_L=TIM2_CNTRL;
//数据转换 每计 1 次数 用时 1us;
IR_Time=IR_Time_H*256+IR_Time_L;
//清零计数器,以计算两次进入中断的时间
TIM2_CNTRH=0;
TIM2_CNTRL=0;
//启动计数器
TIM2_CR1_CEN=1;
//如果时间间隔大于11ms,说明接收到启动码 (引导码 9000us 高电平)
if(IR_Time>11000)
{
IR_Start=1; // 启动标志置一
IR_Num=0; // 清零IR_Num,保证数据的准确性,该语句可以保证不会因为接收到部分数据而
} // 导致数据不准确,原理是启动后必须接收到全部数据,数据才有效
//数据时间间隔大余1.05ms,故不在这个范围则说明不是数据,则返回
if(IR_Time<1050)
{
return; // 退出操作,不再往下执行语句;
}
//如果已经收到启动代码,且数据在有效范围内
if((IR_Start==1) && (IR_Time<2600))
{
//因为先发地址高位,所以要向右移动
IR_data<<=1; // 0000 0100 -> 0000 1000 -> 0001 0000 注意:左移,补 0 ;
//如果数据间隔大于数据0和数据1中间数值,则认为收到数据1
if(IR_Time>1700)
{
IR_data|=1; // 例:0000 1000 | 0000 0001 -> 0000 1001 让最低位 置 1;
}
//收到一位后IR_Num加1
IR_Num++;
//如果IR_Num>31,即等于32,33,34....(为保证可靠,用大于)时,说明数据已经收完
if(IR_Num>31)
{
//数据收完后接收结束标志置位
Sign_Data_Ok=1;
//启动标志清零
IR_Start=0;
//收到全部数据后关闭定时器,可节能,也避免出错
TIM2_CR1_CEN=0;
}
}
IR_Data();// 对数据进行转换;
}
*********************************/
// 初始化:TIME2;
void Init_TIME2(void)
{
// 自动分频器 TIMx_PSCR
//TIM2_PSCR_PSC=1; //0000 0001: 1MHz,计数器为1时定时时间约1us (默认上电时,16MHz,8分频; 再 2 预分频成 1MHz;
TIM2_PSCR_PSC=4; // 主时钟 16MHz, TIM2 采用 16 分频 = 1MHZ(1us);
//自动重装为10000保证正常接收过程中不会溢出
TIM2_ARRH=0xff;
TIM2_ARRL=0xff;
// ARRH/ARRL: 当自动装载的值为 0 时,计数器不工作;
TIM2_EGR_UG=1; //重新初始化寄存器
// UG 产生更新事件 0:无动作; 1 重新初始化计数器,并产生一个更新事件
// 注意,预分频器的计数器也被清 0;
}
/**********************************************************************
* 函数: TIM2 初始化
* 功能:
* 输入:
* 输出:
16位 向上计数 和 自动装载计数器;
4位可编程;分频系数:1-32768 之间的 2 的幂;
分频,向上计数,自动重装载
***********************************************************************/
void Init_TIME2_2(void)
{
TIM2_ARRH = (u8)(1000 >> 8);
TIM2_ARRL = (u8)(1000);
TIM2_PSCR = 0x04; // 16M/(2^4) = 1M
TIM2_EGR = 0x01; // 产生更新事件
TIM2_SR1 = (~0x01); // 清除更新中断标志;
TIM2_CR1 |= 0x01; // 使能 计数器
TIM2_IER |= 0x01; // 更新中断使能;
}
#pragma vector = 15
__interrupt void Inter_Timer2_Over(void)
{
//TIM1_SR1 = 0x00; // 中断标志位 清 0
TIM2_SR1 = (~0x01); // 清除无更新 中断 标志;
time_cnt++;
if(time_cnt > 999)
{
time_cnt = 0;
LED = !LED;
}
// TIM1_CR1_CEN = 0; // 停止记数;
}
/**********************************************************************
* 函数: Uart1_Init(void)
* 功能: Uart1 串口初始化环境设置;
* 输入: 无;
* 输出: 无
***********************************************************************/
void Init_UART1(void)
{
UART1_CR1 = 0x00; // 0000 0000 (5:使能)(4: 1个起始位,8个数据位);一位起始位,八位数据,不校验
//UART1_CR2 = 0x2c; // 0010 1100 (开打接收中断,发送中断可以不设置,发送是我们主动发送的)(开启 发送使能,接收使能)()允许接收中断 发送接收使能
//UART1_CR2 = 0x08; // 0000 1000 发送使能 1开启;不要发送中断 ,不要接收中断;
UART1_CR3 = 0x00; // 0000 0000 一位停止位
// UART1_BRR2 = 0x0b; // 波特率 115200@ 16Mhz // BRR2 要先写于 BRR1;
// UART1_BRR1 = 0x08;
UART1_BRR2 = 0x03; // 波特率 9600 @ 16Mhz(16 000 000 /9600) = 1667;
UART1_BRR1 = 0x68; // 1667 的 16进制:(1667 = 0x0683 ) UART_DIV = 0x0683; UART1_BRR2 =0X03; UART1_BRR1 = 0X68;
//4.使能发送和接收功能
UART1_CR2 = 0x2C; // 0010 1100 开启: ( 发送 + 接收 使能 ) +( 接收 中断)
//UART1_CR2 = 0x0C; // 0000 1100 开启: ( 发送 + 接收 使能 )
/*
7-TIEN 发送 中断使能;
6-TCIEN 发送 完成 中断 使能;
4-ILIEN IDLE 中断 使能;
2-REN 接收使能;
3-TEN 发送使能;
5-RIEN 接收 中断使能;
*/
//UART1_CR2 = 0x08; // 0000 1000 开启: 发送使能; 关闭:接收使能; 不要发送中断 ,不要接收中断?}
}
/**********************************************************************
* 函数: eeprom_read( u8 addr){
* 功能: EEPROM 指定地址读出一个数据
* 输入: 无;
* 输出: 有
***********************************************************************/
u16 eeprom_read( u8 addr)
{
u8 *p;
p=( u8 *)(0x4000+addr);
return *p;
}
/**********************************************************************
* 函数: Delay_Nms(u16 x)
* 功能: 延时Nms;
* 输入: int x;
* 输出: 无
***********************************************************************/
void Delay_Nms(u16 x)
{
u16 a,b;
while(x--)
{
for(a=0; a<18; a++)
{
for(b=0; b<176; b++); // 175->998us; 176->1.00425ms;
}
}
}
/**********************************************************************
* 函数: Delay_1ms(int i)
* 功能: 1ms 延时
* 输入: 无
* 输出: 无
***********************************************************************/
void Delay_50us(u16 i)
{
u8 j;
while(i--)
{
for(j=0; j<154; j++) //50us基准延时程序
{
;
}
}
}
/**********************************************************************
* 函数: Delay_1ms(int i)
* 功能: 38 KHz
* 输入: 无
* 输出: 无
***********************************************************************/
void Delay_13us_duli(u16 i)
{
while(i--)
{
for(u8 j=0; j<30; j++) //38KHz 基准延时程序 高电平 13us.= 26us;
{
;
}
}
}
/**********************************************************************
* 函数: Delay_1ms(int i)
* 功能: 38 KHz
* 输入: 无
* 输出: 无
35 -> (37.7-38 KHz);
***********************************************************************/
void Delay_13us(u16 i)
{
while(i--)
{
for(u8 j=0; j<35; j++) //38KHz 基准延时程序 高电平 13us.= 26us;
{
;
}
}
}
//发射 38KHz 的程序; 1000 000 us / 38 000 Hz = 26.315789 us
void khz_38()
{
IR = 1;
// LED = 1;
Delay_13us(1);
IR = 0;
// LED = 0;
Delay_13us(1);
// khz(116); // 3.028 ms
// khz(64); // 2.006 ms
// khz(40); // 1.052 ms
// delayms(125); // 2.012 ms
// delayms(65); // 1.054 ms
// delayms(93); // 1.5 ms
}
/**********************************************************************
* 函数: Delay100us(void)
* 功能: 100us 延时 精准; 误差 0us
* 输入: 无;
* 输出: 无
***********************************************************************/
void Delay_100us(void)
{
Delay_50us(2);
}
/**********************************************************************
* 函数: LED_Flash()
* 功能: 指示灯
* 输入: 无
* 输出: 无
***********************************************************************/
void LED_Flash(u8 x)
{
u8 i;
for (i = 0; i<= x; i++)
{
LED = 0;
Delay_Nms(3);
LED = 1;
Delay_Nms(3);
}
LED = 1;
}
/**********************************************************************
* 函数: GPIO_Init_Time()
* 功能: IO 端口初始化配置;
* 输入: 无;
* 输出: 无
***********************************************************************/
void GPIO_Init()
{
PA_DDR |= 0x08; // 0000 1000; 1:输出;0:输入 ( PA1_KEY 按键 上拉输入;)
PA_CR1 |= 0x08; // 0000 1000; 1:推挽;0:开漏;
PA_CR2 = 0x00; // 0000 0000;
PB_DDR |= 0x10; // 0001 0000; 1:输出;0:输入 (PB4_LED指示灯 推挽输出 110)
PB_CR1 |= 0x30; // 0011 0000; 1:推挽;0:开漏;
PB_CR2 = 0x00; // 0000 0000;
PC_DDR |= 0xF0; // 0000 0000; 1:输出;0:输入 PA1 按键上拉输入;
PC_CR1 |= 0xF0; // 1111 0000; 1:推挽;0:开漏;
PC_CR2 = 0x00; // 0000 0100
PD_DDR |= 0x0C; // 0000 1100; 1:输出;0:输入 ( PA1_KEY 按键 上拉输入;)
PD_CR1 |= 0x0E; // 0000 1110; 1:推挽;0:开漏;
PD_CR2 = 0x00; // 0000 0000;
// 端口初始化设置;-----------------------------------------------------------------------------
PA_ODR |= 0xFF; // 0x3F: 1111 1111; |= 将 PA端口全部置 1 (高电平 )
PB_ODR |= 0xFF;
PC_ODR |= 0xFF;
PD_ODR |= 0xFF;
}
void send_1(void)
{
/////////////////////////////////////////////////////
u8 end_count = 3; //发送 公共的 0.56ms 高电平
IR = 1;
u8 count = 0;
u8 count0 = 0;
do
{
IR = 1;
Delay_13us(1);
IR = 0;
Delay_13us(1);
count++;
if(count >= 8)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
/////////////////////////////////////////////////////
end_count = 7; //发送 底电平 0.56ms 1.125 ms
IR = 0;
count0 = 0;
count0 = 0;
do
{
count++;
if(count >= 100)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
}
// send_1(); // 数据 0; 1.125
// send_0(); // 数据 0; 2.25
void send_0(void)
{
/////////////////////////////////////////////////////
u8 end_count = 3; //发送 公共的 0.56ms 高电平
IR = 1;
u8 count = 0;
u8 count0 = 0;
do
{
IR = 1;
Delay_13us(1);
IR = 0;
Delay_13us(1);
count++;
if(count >= 7)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
/////////////////////////////////////////////////////
end_count = 21; //发送 底电平 0.56ms 1.125 ms
IR = 0;
count0 = 0;
count0 = 0;
do
{
count++;
if(count >= 100)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
}
void send(u8 dat)
{
u8 s = 0, user = 0, shu_ju = 0, hc = 0;
u8 count0 = 0;
/**********发送引导码**********************/
end_count = 8; // 发送 9ms 起始码的高电平
IR = 1;
count = 0;;
do
{
IR = 1;
Delay_13us(1);
IR = 0;
Delay_13us(1);
count++;
if(count >= 42)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
end_count = 53; // 发送 4.5ms 结束码的低电平
IR = 0;
count0 = 0;
do
{
count++;
if(count >= 100)
{
count = 0;
count0 ++;
}
}
while(count0 < end_count);
/**********发送 系统 码***********************/
user = system;
for(u8 s = 0; s < 8; s++)
{
hc = user & wy[s]; // 发送 脉冲 间距
if(hc == 0)
{
send_1(); // 数据; 2.25
}
else
{
send_0(); // 数据; 1.125
}
}
/********** 发送 系统 反码 ***********************/
for(u8 s = 0; s < 8; s++)
{
hc = user & wy[s]; //发送脉冲间距
if(hc == 0)
{
send_0(); // 数据; 1.125
}
else
{
send_1(); // 数据; 2.25
}
}
/**********发送 客户 码 ***********************/
user = 0x0C;
for(u8 s = 0; s < 8; s++)
{
hc = user & wy[s]; // 发送 脉冲 间距
if(hc == 0)
{
send_1(); // 数据; 2.25
}
else
{
send_0(); // 数据; 1.125
}
}
/**********发送 客户 反码 ***********************/
for(u8 s = 0; s < 8; s++)
{
hc = user & wy[s]; // 发送 脉冲 间距
if(hc == 0)
{
send_0(); // 数据; 1.125
}
else
{
send_1(); // 数据; 2.25
}
}
send_1(); // 数据; 2.25
}
/**********************************************************************
* 函数: main()
* 功能: 主函数;
* 输入: 无;
* 输出: 无
***********************************************************************/
void main()
{
asm("sim"); // disable all interrupt EA=0; // 关闭 中断;
CLK_Init(); // 时钟初始化| 没有打开时钟计时,在需要时,才开启;
// TIM1_Init(16000,1000); // 定时器初始化| f=16M/16000=1kHz time=1ms*1000=1s
GPIO_Init(); //
asm("rim"); //enable all interrupt EA=1; // 打开 中断;
// TIM1_CR1 |= 0x01; //开始计数
while(1)
{
// IR = 1;
//// LED = 1;
// Delay_13us(1);
// IR = 0;
//// LED = 0;
// Delay_13us(1);
// khz_38();
if(!KEY)
{
Delay_Nms(10);
if(!KEY)
{
LED_Flash(1);
send(0xFF); // 发送 红外 编码;
}
}
}
}
联系人:客服在线
手机:全工:13903011251
电话:李R:13530006400
邮箱:729986191@qq.com
地址: GUANGDONG PROVINCE