各位先前:
我這裡有段程式, 麻煩幫我查看一下,
當同時設定使用PWM和RS232時, RS232便無法接收字元, 但可以傳送字元, 而已RS232的initial中如”同時”設定TXIE = 1和RCIE = 1,RS232便無法傳和收,
不知是那裡register設定有遺漏,查了很久還是查不出來快要發轟囉~, 麻煩大家有空幫我查看一下, 感謝!!感謝!!
IC是16F887A, 使用8MHZ x’tal,
#include <pic.h>
//#include "pic1687x.h"
typedef unsigned char u8;
typedef unsigned int u16;
// setting
void pic_set();
void led_set();
void rs232_set();
void pwm_set();
// RS232
void put_str(const char *data);
void put_hex(u8 hex);
void put_byte(unsigned char byte);
void show_char(u8 da);
void show_da(u8 da);
u8 tx_da(u8 da);
u8 rx_da(u8 da);
// delay
void delay_1();
void delay_2();
void delay(u16 count);
// other
void led_act();
void syson_show();
u8 i2c_master_id = 0x11;// iic master ID address
u8 ascii_code[17] = "0123456789ABCDEF";
u8 tempi;
u16 timer2_counter;
bit rs232_rx_flag = 0;
bit led_act_flag = 0;
u8 rs232_buf = 0;
u8 rs232_cmd_count = 0;
u8 rs232_cmd = 0;
u8 rs232_cmd_buf[9];
//---------------------------------------------------------------------
void main()
{
// pic_set();
led_set();
rs232_set();//<----------------當有設定RS232, 就無法接收字元, 但可以傳收字元
pwm_set();//<----------------
led_act();
syson_show();
while(1)
{
// if(rs232_rx_flag == 1)
if(RCIF == 1) // rs232接收中斷旗標
{
led_act();
rs232_rx_flag = 0;
if(rs232_buf == '1') // 當接收到RS232的'1'
{
led_act();
put_str("rnPWM Duty Cycle +");
CCPR1L = CCPR1L + 1;// Duty Cycle,
}
if(rs232_buf == '2') // 當接收到RS232的'2'
{
led_act();
put_str("rnPWM Duty Cycle -");
CCPR1L = CCPR1L - 1;// Duty Cycle,
}
// rs232_rx_cmd();
}
/*
if(OERR == 1) // (debug), 因為當終端機"連續"送字串時, RS232接收會出現
{ // RSR暫存器資料轉移出現error, OERR 會位元會設為1,
CREN = 0; // 將RS232接收致能"CREN"重置即可!!
CREN = 1;
}
*/
}
}
//---------------------------------------------------------------------
void syson_show()
{
// put_str("rn");// r=行頭,n=換行
put_str("rn------------------");
put_str("rnFSP-GROUP 韌體中心");
}
//---------------------------------------------------------------------
void put_str(const char *data)
{
do
{
while(!(TXSTA & 0x02));
TXREG = *data;
}
while( *data++ );
}
/*-------------------------------------------------------*/
//Write a hex to USART,
//由RS232傳送1個byte的資料, 1個byte的資料轉換成ASCII 2個字元
void put_hex(u8 hex)
{
put_byte( ascii_code[(hex & 0xf0)>>4] );
put_byte( ascii_code[(hex & 0x0f)] );
}
/*---------------------------------------------------------*/
// Write a byte to the USART, 由RS232傳送1個byte的資料, 格式為16進制
void put_byte(unsigned char byte)
{
/* output one byte */
while(!(TXSTA & 0x02)); /* set when register is empty */
TXREG = byte;
}
//---------------------------------------------------------------------
void show_da(u8 da) // 從RS232顯示1個byte的資料,格式為16進制
{
u8 d[3];
d[0] = ( da & 0x0f ); // 取byte資料的低位元
d[1] = tx_da( d[0] ); // 低位元轉換成16進制
d[0] = ( da >> 4 ) & 0x0f; // 取byte資料的高位元
d[2] = tx_da( d[0] ); // 高位元轉換成16進制
for(d[0]=2; d[0]>0; d[0]--)
{
while(TXIF == 0); // TXIF=0, 代表TXREG裡有資料還沒傳出去
TXREG = d[d[0]]; // TXIF=1, 代表TXREG是沒有資料了
}
}
//---------------------------------------------------------------------
void show_char(u8 da) // 由RS232 顯示字元
{
if( TXIF = 1 ) // 檢查TXIF傳送旗標是否為1,1代表TXREG BUFFER是空白的
{
TXREG = da;
delay_1();
}
}
//----------------------------------------------------------------
u8 tx_da(u8 da) // 要從RS232傳出去一個數字資料,
{ // 轉換數字資料型態會是十六進制,
if( da<=9 )
{ da = da+0x30; // 將1個byte數字資料轉換成 ASCII CODE
return( da );
}
else
{ da = da+0x37; // 將1個byte數字資料轉換成 ASCII CODE
return( da );
}
}
//----------------------------------------------------------------
u8 rx_da(u8 da) // 要從RS232收一個數字資料,
{
if( (da>=0x30) && (da<=0x39) )
{
da = da-0x30; // ASCII CODE 轉換成1個byte的數字資料
return( da );
}
else if( (da>=0x41) && (da<=0x46) )
{
da = da-0x37; // ASCII CODE 轉換成1個byte的數字資料
return( da );
}
}
//---------------------------------------------------------------------
void led_act()
{
RB5 = 1; delay_1();
RB5 = 0; delay_1();
}
//---------------------------------------------------------------------
void delay_1()
{
// use 4MHZ, 1us~ // use 8MHZ, 0.5us~
u8 co1; u16 co2;
for(co1=0; co1<8; co1++)
for(co2=0; co2<1000; co2++);
}
//---------------------------------------------------------------------
void delay_2()
{
// use 4MHZ, 1us~ // use 8MHZ, 0.5us~
u8 co1; u16 co2;
for(co1=0; co1<2; co1++)
for(co2=0; co2<50000; co2++);
}
//---------------------------------------------------------------------
void delay(u16 count)
{
// use 4MHZ, 1us~ // use 8MHZ, 0.5us~
while(count != 0)
count--;
}
//*********************************************************
// ISR
//*********************************************************
void interrupt isr()
{
if(RCIF == 1) // rs232接收中斷旗標
{ // 檢查RS232 RCIF接收旗標是否為1,1代表RCREG BUFFER有資料
// RCIF = 0; // RS232 RCIF不用軟體去清除中斷旗標,當RCREG資料被讀出來就會自動清除
rs232_buf = RCREG;// 將RCREG內容取出後,RCIF自動設為0
rs232_rx_flag = 1; // main check flag
}
}
//*********************************************************
// ISR
//*********************************************************
//---------------------------------------------------------------------
void pwm_set() // pwm setting, use timer2
{
TRISC = 0x00; // 設定RC1和RC2為PWM輸出腳, 設定PORTC IO port 為output模式
PR2=200; // 週期值Period,
CCPR1L=10; // 責任週期Duty Cycle,
T2CON = 0b00000100; // TMR2 = on,
CCP1CON = 0b00001100; // and enable PWM mode
CCP2CON = 0b00001100; // and enable PWM mode
CCP1X=1;
CCP1Y=1;
CCP2X=1; // set bit 1
CCP2Y=1; // set bit 0
}
//---------------------------------------------------------------------
void rs232_set() // RS232 function setting
{
// SPBRG = 25; // 4MHz, 設定BAUD RATE參數, 9600
SPBRG = 51; // 8MHz, 設定BAUD RATE參數, 9600
BRGH = 1; // 設定BAUD RATE參數, High speed/Low speed
SYNC = 0; // rs232設定"非同步模式"
SPEN = 1; // 致能rs232模組, RC6和RC7為RS232 TX/RX
TX9 = 0; //
RX9 = 0; //
TRISC6 = 0; // RC6為TX, 設定為數位輸出
TRISC7 = 1; // RC7為RX, 設定為數位輸入
TXEN = 1; // RS232傳送致能
CREN = 1; // RS232接收致能
// TXIE = 1; // rs232 TX 中斷致能, ?致能後RS232就不能動?
RCIE = 1; // rs232 RX 中斷致能, ?致能後RS232就不能動?, 而已RCIE沒有致能, RCIF也會產生中斷!
// 內部eeprom的EEIF也是一樣的情形, EEIE不用致能, EEIF就會自己產生中斷! why???
// 發現, 如沒有使用timer0(沒有設定T0IE = 1), 只有使用i2c介面及rs232介面, 各自的IE就要設定! why?
// 而已TXIE和RCIE不能同時設定! why?
}
//---------------------------------------------------------------------
void led_set()
{
TRISB = 0b00000000; // 設定PORTB IO port 為output模式
}
//---------------------------------------------------------------------
void pic_set()
{
GIE = 1; // Global interrupt enable
PEIE = 1; // 週邊中斷致能
// TMR1ON = 1; // timer1開始計數
// TMR2ON = 1; // timer2開始計數
}