Forums

ATmeag128 8Mhz with Z85c30 SCC(zilog)

Started by sebastiankoo February 25, 2008
Hello. 

I am coding to build-up SDLC(HDLC) in z85c30 with MCU, 
ATmega128.  

I am trying to build-up SDLC(HDLC) protocal
H/w environment is z85c30(CMOS) with 4.91520Mhz crystal for PCLK.
Also, z85c30's D0~D7 is connected with MCU in un-multiplexed
mode(=direct)

  communication specification is as below
    - 38.4kbps
    - NRZI mode
    - Response time: 50ms
    - Address: Lower=70h   Higher=05h
    - control field: 13h
    - Information field 
       if first text = 20, SDR(Master -> Slave)
       if first text = 30, SD(Slave -> Master)

      For SDR, Information field length is  20 + 7bytes (8bytes)       
      For SD, Information field length is  30 + 11bytes (12bytes)


 with this specification, I do code as below. 
 For Rx, I use interrupt drived method, and for Tx just polling 
 method used.

 Now, this code works on only Rx. Tx does not work, which means master 
 could not get data.
 I can receive data, but can not send(Tx) to master device.

Could you please check this procedure in c lang with any advice? 
I hope I may get some helpful hands from your side.

---------code in c lang: Main
function-------------------------------------
void main(void){
  
  __disable_interrupt(); //All interrupt disable

  SETBIT(INTACK); //NO interrupt ack.
  z85c30_set(); //sub-function will be shown below 
  z85c_enable(); //sub-function will be shown below

  __enable_interrupt(); //All interrupt enable

  while(1){
          
     switch(sdlcstep){
            case 0: //Rx start
                    Write_reg(5,0x60); //Tx 8bits, Tx disable
                    Write_reg(3,0xcc); //Rx 8bits, Rx CRC enable, Address

                                         search mode
                    Write_reg(3,0xcd); //Rx enable
                    Write_Reg(1,0x10); //Rx int on all received character

                                         or special condition
                    break;
            case 1: //If Rx Ok.
                    if(RxOk){
                      
for(icnt=4;icnt<=10;icnt++)sdlcRdata[icnt]=sdlcRbuf
                           [icnt];//READ DATA  
                       RxOk = 0;    
                       for(i=0;i<=15;i++)Txbuffer[i] = Txdata[i]; //input

                                                             data to
write
                       sdlcStep++;
                    }
                    break;
            case 2: //Rx disable & Tx Start
                   Write_Reg(3,0xcc);//disable rx 
                   Write_Reg(1,0x00);//disable rx int
    
                   Write_Reg(0,0x80); //reset txgenerator
                   Write_Reg(5,0x69); //Tx 8bit-char,Tx Crc ena, Tx ena
                   Write_Reg(10,0xa0); //set preset + nrzi
                   sdlcStep++;
                   break;
            case 3: //write tx data to tx buffer if it is empty.
                   if(read_reg(0)&0x04){//if Tx buffer empty
                      Write_Data(sdlcTbuf[tx_data_cnt]);
                      tx_data_cnt++;
                      f(tx_data_cnt >= 15) sdlcStep++;
                   }
                  break;
            case 4: //EOF to append CRC to frame
                   if(read_reg(0)&0x40){
                      Write_Reg(0,0xc0);//EOM & CRC Gen; Reset Tx 
                                          Underrun/EOM Latch
                      sdlcStep++;
                   }
                  break;
            case 5: //Tx disable & Rx ready
                   Write_Reg(5, 0x60); //TX disable
		   Write_Reg(9,0x80); //Ch A reset
                   delay(10); //about 5-clks of PCLK.
                   Write_Reg(9, 0x0a);  //DONE: MIE, NV
                   sdlcStep =0; //GO to first case 0
                  break;
        }// switch~ case
    }//while
 }//main
---------code in c lang: Main
function------------------------------------


---------code in c lang: Sub-function called by main
function--------------
 void z85c30_set(void)
{
	Write_Reg(9, 0xc0);	//DONE: Force H/W reset
	delay(20);
	Write_Reg(4, 0xa0);	//DONE: x32 clk, SDLC mode
	 
	Write_Reg(3, 0xC0);	//DONE: Rx,-8bit/character
	Write_Reg(5, 0x60);	//DONE: Tx,-8bit/character
	
	Write_Reg(6, 0x70);     //DONE: Address(Lower)
	
	Write_Reg(7, 0x7e);     //DONE: SDLC SYNC (01111110 sdlc)
	//Write_Reg(9, 0x00);	//No reset(null command)
	
	Write_Reg(10, 0x20);    //DONE: CRC Preset=0, NRZI mode
	Write_Reg(14, 0x60);    //DONE: DPLL,BRG Disable
	
	Write_Reg(11, 0x70);    //DONE: CLK SOURCE CONTROL Rx CLK:
                                  DPLL out, Tx CLK:BRG output
	
	/****TC Table at 4.9152Mhz,condition
	 ----------------------------------------------------
	    clock factor     TC(38400bps)
	 ---------------------------------------------------
	       1            0x3e(62)
	       16           0x02(2)
	       32           0x00(0)
	       64           -2
	********************************************/
	Write_Reg(12, 0x00);    //DONE: BRG TC low
	Write_Reg(13, 0x00);    //DONE: BRG TC High
}

void z85c30_enable(void)
{
                                          
        Write_Reg(14, 0x80);	//DONE: DPLL source <-BRG Output(Rx
                                  clock)                                 
	Write_Reg(14, 0x03);	//DONE: NULL CMD(NO effect), BRG enable,
                                  BRG source: PCLK input
	Write_Reg(14, 0xe3);	//DONE: BRG enable, DPLL:SET NRZI
	Write_Reg(14, 0x23);	//DONE: BRG enable
			        //search mode:DPLL starts to search first
                                  edge of data in	
	 
	Write_Reg(15,0x01);     //WR7' : enable
        Write_Reg(7,0x20);      //0x23 : Receive 2-nd byte of CRC
        Write_Reg(15,0x40);     //Tx underrun/EOM interrupt enable
	
	Write_Reg(9, 0x0a);  //DONE: MIE, NV
}
---------code in c lang: Sub-function called by main
function-------------
    

---------code in c lang: Rx interrupt service
routine---------------------
__interrupt void int_RxISR(void)
 {
   int i;
   unsigned char nCmdCode;
   unsigned char nData;
   
   CLEARBIT(PORTB,6);//INTACK active low for daisy-chain

   for(i=0;i<9;i++){
   
   nCmdCode = read_reg(0x03);
   
   if(nCmdCode&0x20){ //Rx Ip occurs
      nData = read_data();//Read Rx buffer
      sdlcRbuf[RxPos++] = nData; //read FIFO data from z85c30 data
register
      switch(RxPos){ //by buffer position
                 case 1:
                        if(sdlcRbuf[0] != 0x70) RxPos = 0; //check first
                                                            lower address
                        break;
                 case 2:
                        if(sdlcRbuf[1] != 0x05) RxPos = 0; //check higher
                                                              adderss
                        break;                        
                 default: 
                        if(RxPos > 12){ //read till CRC 2bytes
                           RxPos=0; RxOk =1; i=8;}
                        break;
      } //switch~case
   } //if RR3 ip
  } //for
} //ISR routine    
---------code in c lang: Rx interrupt service
routine---------------------


On Mon, 25 Feb 2008 09:41:22 -0600, "sebastiankoo" <sebikoo@naver.com>
wrote in comp.arch.embedded:

> Hello. > > I am coding to build-up SDLC(HDLC) in z85c30 with MCU, > ATmega128. > > I am trying to build-up SDLC(HDLC) protocal > H/w environment is z85c30(CMOS) with 4.91520Mhz crystal for PCLK. > Also, z85c30's D0~D7 is connected with MCU in un-multiplexed > mode(=direct)
[snip]
> with this specification, I do code as below. > For Rx, I use interrupt drived method, and for Tx just polling > method used. > > Now, this code works on only Rx. Tx does not work, which means master > could not get data. > I can receive data, but can not send(Tx) to master device. > > Could you please check this procedure in c lang with any advice? > I hope I may get some helpful hands from your side.
It's been a long time since I programmed a Z85C30, and then it was on a Z80. I think the last time was before AVR architecture even existed. But I do see a problem in your C code...
> ---------code in c lang: Main > function------------------------------------- > void main(void){ > > __disable_interrupt(); //All interrupt disable > > SETBIT(INTACK); //NO interrupt ack. > z85c30_set(); //sub-function will be shown below > z85c_enable(); //sub-function will be shown below > > __enable_interrupt(); //All interrupt enable > > while(1){ > > switch(sdlcstep){ > case 0: //Rx start > Write_reg(5,0x60); //Tx 8bits, Tx disable > Write_reg(3,0xcc); //Rx 8bits, Rx CRC enable, Address > > search mode > Write_reg(3,0xcd); //Rx enable > Write_Reg(1,0x10); //Rx int on all received character > > or special condition > break;
In this case you do not modify the value of "sdlcstep". You don't show the definition or initialization of this variable in the code you posted, but I assume it has external linkage and static storage duration, so it is initialized to 0. The first time into this loop, the value is 0. In the case for the value of 0, you never change the value. So your loop will always execute this case forever. So you never get farther into your state machine, never get to where you try to transmit. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://c-faq.com/ comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html